Skip to content

Commit 47af900

Browse files
authored
fix bug and add smoke test (#510)
* updates Signed-off-by: Jessie Frazelle <github@jessfraz.com> * updates Signed-off-by: Jessie Frazelle <github@jessfraz.com> --------- Signed-off-by: Jessie Frazelle <github@jessfraz.com>
1 parent f2fd5d1 commit 47af900

21 files changed

+901
-254
lines changed

.github/workflows/win-ca-smoke.yml

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
name: win-ca-smoke
2+
3+
permissions:
4+
contents: read
5+
6+
on:
7+
pull_request:
8+
push:
9+
branches: [ main, master ]
10+
11+
jobs:
12+
smoke:
13+
runs-on: windows-latest
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
node: [20, 22]
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- name: Setup Node
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: ${{ matrix.node }}
25+
26+
- name: Setup Python
27+
uses: actions/setup-python@v4
28+
with:
29+
python-version: '3.13'
30+
31+
- name: Install uv
32+
uses: astral-sh/setup-uv@v4
33+
with:
34+
version: latest
35+
enable-cache: true
36+
cache-dependency-glob: uv.lock
37+
38+
- name: Install dependencies
39+
shell: pwsh
40+
run: |
41+
uv sync --extra dev
42+
43+
- name: Create local root CA and server cert (untrusted)
44+
shell: pwsh
45+
run: |
46+
./scripts/win/create-local-ca.ps1 -PfxPath servercert.pfx -PfxPassword 'pass' -NoTrust
47+
48+
- name: HTTPS smoke fails before trust
49+
id: pre_smoke
50+
continue-on-error: true
51+
shell: pwsh
52+
env:
53+
NODE_EXTRA_CA_CERTS: ${{ github.workspace }}\root.pem
54+
WIN_CA_SMOKE: '1'
55+
WIN_CA_EXPECT_SUCCESS: '0'
56+
run: |
57+
$job = Start-Job -ScriptBlock { node scripts/https-server.mjs }
58+
try {
59+
$deadline = (Get-Date).AddSeconds(30)
60+
do {
61+
$ok = Test-NetConnection -ComputerName 127.0.0.1 -Port 4443 -WarningAction SilentlyContinue -InformationLevel Quiet
62+
if (-not $ok) { Start-Sleep -Milliseconds 200 }
63+
} while (-not $ok -and (Get-Date) -lt $deadline)
64+
if (-not $ok) { throw 'HTTPS server did not become ready in time' }
65+
uv run pytest kittycad/tests/test_win_ca_smoke.py --maxfail=1 --disable-warnings -q
66+
} finally {
67+
Stop-Job -Job $job -PassThru | Remove-Job
68+
}
69+
70+
- name: Assert failure without trusted root
71+
if: steps.pre_smoke.outcome != 'failure'
72+
shell: pwsh
73+
run: |
74+
Write-Host 'Expected certificate validation to fail before trusting root CA'
75+
exit 1
76+
77+
- name: Create and trust local root CA and server cert
78+
shell: pwsh
79+
run: |
80+
./scripts/win/create-local-ca.ps1 -PfxPath servercert.pfx -PfxPassword 'pass'
81+
82+
- name: HTTPS smoke (start server and run pytest)
83+
shell: pwsh
84+
env:
85+
NODE_EXTRA_CA_CERTS: ${{ github.workspace }}\root.pem
86+
WIN_CA_SMOKE: '1'
87+
WIN_CA_EXPECT_SUCCESS: '1'
88+
run: |
89+
$job = Start-Job -ScriptBlock { node scripts/https-server.mjs }
90+
try {
91+
$deadline = (Get-Date).AddSeconds(30)
92+
do {
93+
$ok = Test-NetConnection -ComputerName 127.0.0.1 -Port 4443 -WarningAction SilentlyContinue -InformationLevel Quiet
94+
if (-not $ok) { Start-Sleep -Milliseconds 200 }
95+
} while (-not $ok -and (Get-Date) -lt $deadline)
96+
if (-not $ok) { throw 'HTTPS server did not become ready in time' }
97+
uv run pytest kittycad/tests/test_win_ca_smoke.py --maxfail=1 --disable-warnings -q
98+
} finally {
99+
Stop-Job -Job $job -PassThru | Remove-Job
100+
}
101+
102+
- name: Cleanup local certs
103+
if: always()
104+
shell: pwsh
105+
run: |
106+
try {
107+
Get-ChildItem -Path Cert:\CurrentUser\Root | Where-Object { $_.Subject -eq 'CN=KittyCAD-Test-Root' } | Remove-Item -Force -ErrorAction SilentlyContinue
108+
Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object { $_.Subject -match 'CN=KittyCAD-Test-Root|CN=localhost' } | Remove-Item -Force -ErrorAction SilentlyContinue
109+
} catch {}
110+
try {
111+
Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object { $_.Subject -eq 'CN=KittyCAD-Test-Root' } | Remove-Item -Force -ErrorAction SilentlyContinue
112+
Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Subject -match 'CN=KittyCAD-Test-Root|CN=localhost' } | Remove-Item -Force -ErrorAction SilentlyContinue
113+
} catch {}
114+
Remove-Item -Path servercert.pfx,root.pem,root.cer -Force -ErrorAction SilentlyContinue

generate/post_processing.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import logging
55
import os
6+
import re
67
from typing import List
78

89
import jsonpatch
@@ -38,10 +39,41 @@ def generate_examples_tests(cwd: str, examples: List[str]):
3839
f.write("\n\n".join(examples_without_imports))
3940
f.close()
4041

42+
_alias_conflicting_option_headers(examples_test_path)
43+
4144
# Post-process with ruff to clean up imports and formatting
4245
format_file_with_ruff(examples_test_path)
4346

4447

48+
def _alias_conflicting_option_headers(examples_test_path: str) -> None:
49+
"""Alias clashing OptionHeaders imports so tests stay lint-clean."""
50+
51+
with open(examples_test_path, "r") as file:
52+
content = file.read()
53+
54+
original_import = "from kittycad.models.web_socket_request import OptionHeaders"
55+
alias_import = (
56+
"from kittycad.models.web_socket_request import OptionHeaders as "
57+
"WebSocketRequestOptionHeaders"
58+
)
59+
60+
if original_import not in content:
61+
return
62+
63+
# Alias the import line for the websocket variant
64+
content = content.replace(original_import, alias_import, 1)
65+
66+
# Update usages to reference the aliased name while preserving whitespace
67+
content = re.sub(
68+
r"WebSocketRequest\((\s*)OptionHeaders",
69+
r"WebSocketRequest(\1WebSocketRequestOptionHeaders",
70+
content,
71+
)
72+
73+
with open(examples_test_path, "w") as file:
74+
file.write(content)
75+
76+
4577
def generate_patch_json(cwd: str, spec_path: str, data: dict):
4678
"""Generate the kittycad.py.patch.json file."""
4779
# Read the original spec file as a dict.

generate/templates/object.py.jinja2

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,8 @@ class {{ name }}(KittyCadBaseModel):
2121
{{ field.name }}: {{ field.type }}
2222
{% endif %}
2323
{% endfor %}
24+
{% if extra_body_lines %}
25+
{% for line in extra_body_lines %}
26+
{{ line }}
27+
{% endfor %}
28+
{% endif %}

0 commit comments

Comments
 (0)