Compare commits

...

27 Commits

Author SHA1 Message Date
55a6155400 WIP: Start using the recursion crate 2024-08-19 11:09:37 -04:00
d41972ee4d Add recursion dependency 2024-08-19 11:09:37 -04:00
2d6c8cfe32 Add electron test for settings being set on home level and overridden by project level (#3527)
Add a test for settings being set on home level and overridden by project level
2024-08-19 10:23:43 -04:00
37c6730c02 Fix CPU-driven churn once Text-to-CAD toast appears in the app (#3523)
* Dispose of requestAnimationFrame loop when component unmounts

* Only run requestAnimationFrame loop when mouse is on canvas

* Better animation loop disposal on canvas mouseout

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* Text-to-cad test flakiness

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* Re-run CI

* Remove arbitrary timeout which may cause us to miss the toast on a fast-running test

* Remove a couple more arbitrary timeouts in text-to-cad tests

* Remove all the arbitrary 5s awaits from these tests

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-19 09:38:47 -04:00
337f828aa4 Franknoirot/electron network regression test (#3525)
* Only show the network health indicator when in the modeling view

* Add test to confirm network health indicator behavior
2024-08-19 08:58:24 -04:00
d845e7c38d playwright robustness: "can do many at once and get many prompts back, and interact with many" (#3524)
* playwright robustness

* try fix the close button
2024-08-19 22:38:17 +10:00
7f50294936 Fix up little differences in file/dir creation logic for electron (#3498)
* Fix up little differences in file/dir creation logic for electron

* Fix typo

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)"

This reverts commit 8e7212f5da.

* Text-to-cad test flakiness

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-19 08:08:07 -04:00
73bbd3f5b7 Revert "Add a test for settings being set on home level and overridden by project level"
This reverts commit 295b98c021.
2024-08-19 14:00:28 +02:00
295b98c021 Add a test for settings being set on home level and overridden by project level 2024-08-19 13:56:30 +02:00
2e24137863 Electron export test #3376 (#3512)
* electron export test #3376

* typo

* increase timeout
2024-08-19 16:29:44 +10:00
5e694961e8 get unit tests running again (#3519) 2024-08-19 14:47:27 +10:00
a1ef4ff86f playwright order in github actions (#3509)
playwright matrix tweak
2024-08-19 14:01:28 +10:00
ccd31b7d6d rename for #3367 (#3508) 2024-08-19 11:55:18 +10:00
b5ddbb7fa7 electron delete project tests (#3507)
add delete projcet tests #3365
2024-08-19 11:49:03 +10:00
4613a7c92e fixup tests get green (#3494)
* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* empty

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add dep

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update export tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* get to green

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixups

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* turn off macos for now

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update typos

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-17 14:15:11 -07:00
a89d8bb8e8 Fix autocomplete for bools (#3502)
* fix autocomplete snippet bool

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix clippu

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
2024-08-16 19:48:09 -07:00
1822021bb3 Get existing web text-to-cad playwright tests back to green (#3496)
* Get text-to-cad playwright tests back to green

* fmt
2024-08-16 15:06:20 -07:00
9d71900caf Test: restart electron with settings intact (#3488)
* Test: restart electron with settings intact

* Make testing-selections 1px less sensitive
2024-08-16 12:24:36 -07:00
0c15299b0e Add a test for searching the projects on the home page (#3486)
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-08-16 14:53:03 -04:00
4def38a698 Add desktop playwright test for restarting onboarding (#3481)
* Add a yarn script to run electron tests locally

* Add plawright electron test restarting onboarding

* Add steps to restart onboarding with no code, and restart from settings button

* The "Opening the bracket" had a step that could occasionally resolve to multiple elements

* Fix my misunderstanding of how to select for the bracket project card

---------

Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-08-16 14:49:51 -04:00
9e4671c6d7 Test on all oses for electron/chrome (#3485)
* try os matrix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* make playwright chrome a thing

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* ignore vector windows

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* use bash

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* bash

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* upfdatges

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix always to cancel

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* fix ubuntu

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu-latest)

* fix debug logs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-16 11:18:33 -07:00
b2707ecc41 Bump serde_json from 1.0.124 to 1.0.125 in /src/wasm-lib (#3473)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.124 to 1.0.125.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.124...1.0.125)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-16 09:37:56 -07:00
53e0277acc Adding projects folder change test (#3482)
* Adding projects folder change test

* Missed a bunch of promises that need awaited

* Await on electronApp.evaluate too
2024-08-16 12:09:02 -04:00
e8d90f171b Bump clap from 4.5.15 to 4.5.16 in /src/wasm-lib (#3472)
Bumps [clap](https://github.com/clap-rs/clap) from 4.5.15 to 4.5.16.
- [Release notes](https://github.com/clap-rs/clap/releases)
- [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/clap-rs/clap/compare/clap_complete-v4.5.15...clap_complete-v4.5.16)

---
updated-dependencies:
- dependency-name: clap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
2024-08-16 07:40:08 -07:00
a6c5493a7f Bump serde from 1.0.207 to 1.0.208 in /src/wasm-lib (#3471)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.207 to 1.0.208.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.207...v1.0.208)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-16 07:39:55 -07:00
2a10688b39 Bump @lezer/highlight from 1.2.0 to 1.2.1 (#3480)
Bumps [@lezer/highlight](https://github.com/lezer-parser/highlight) from 1.2.0 to 1.2.1.
- [Changelog](https://github.com/lezer-parser/highlight/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lezer-parser/highlight/compare/1.2.0...1.2.1)

---
updated-dependencies:
- dependency-name: "@lezer/highlight"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-16 07:39:44 -07:00
8400e06dd6 Lf94/tauri to electron (#3315)
* Get electron building something at all

* Merge Frank test setup work (#3418)

* Working window.electron.getPath

* Loading project-specific settings in electron tests

* Simplify test until we can get snapshots/traces working in electron tests

* test tweaks

---------

Co-authored-by: Frank Noirot <frank@kittycad.io>

* add test #3375 and #3420

* put kcl files together

* move files

* can sort projects #3362

* File in the file pane should open with a single click #3385

* pressing delete on home screen should do nothing #3387

* add aria labels to icons

* Rename and delete projects, also spam arrow keys when renaming #3364 #3365 #3259

* Fix up paths

* Update flake.nix to support Electron

* Remove a layer of indirection

* Work without a web server

* Fix settings#projectDir link on home

* Fix login (requires new @kittycad/lib WHICH IS NOT INCLUDED HERE)

* Lee: Tests are broken because auth skip needs to happen

* get setting override envs passed through

* tweak eletron CI

* yml tweak

* fmt

* NUKE tauri shit post merge with main

* another test auth tweak

* Revert "another test auth tweak"

This reverts commit b2254b10af.

* try CI again

* CI tweaks

* SKIP_AUTH true now on playwright

* Skipping auth when NODE_ENV=development now

* fmt

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* Use BASE_URL()

* fix exists

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix foldername for macos

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update for windows

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix version in lower right

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup unused imports

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* progress on is playwright

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix test folders

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix fmt

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* remove tauri from actions bullshit

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* remove tauri dir

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixups the coredump async shit

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* node env dev

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix cancellable

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* cleanup unnessary things

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* env vars

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* Bring back fix for NOT using hardcoded main.kcl

* env

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fmt

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* Revert "updates"

This reverts commit da5d9f1043eb94404e8b3f8044088e990e34a4ef.

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* remove tauri clippuy

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* less retries for now, no debug

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* tsconfig

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* small tsc fix

* update some tsc

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* tsc env

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix other tsc

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* small change for routeLoaders

* rm old screenshot

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix auth

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix last onew

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* auth clean up

* fix package.json

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* dissmissed screen on tests

* add waits between files being written

* put back retried

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix weird programMemory Map issue

* put private back

* Revert "put private back"

This reverts commit d311b978ca.

* Revert "fix weird programMemory Map issue"

This reverts commit 6c387bdf62.

* remove serde-wasm-bindgen

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add env

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* fix tests

* more test tweaks

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* another tweak

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* more test tweaks

* more tweaks

* increase macos timeout

* try fix macos

* disable macos playwright tests

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Kurt Hutten <k.hutten@protonmail.ch>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Adam Sunderland <iterion@gmail.com>
Co-authored-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Jess Frazelle <jessfraz@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-08-16 21:15:42 +10:00
269 changed files with 8379 additions and 13387 deletions

View File

@ -1,3 +1,3 @@
[codespell]
ignore-words-list: crate,everytime,inout,co-ordinate,ot,nwo,absolutey,atleast,ue,afterall
skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md,./src-tauri/gen/schemas
skip: **/target,node_modules,build,**/Cargo.lock,./docs/kcl/*.md,./src-tauri/gen/schemas,.yarn.lock,**/yarn.lock

View File

@ -1,3 +1,5 @@
NODE_ENV=development
DEV=true
VITE_KC_API_WS_MODELING_URL=wss://api.dev.zoo.dev/ws/modeling/commands
VITE_KC_API_BASE_URL=https://api.dev.zoo.dev
VITE_KC_SITE_BASE_URL=https://dev.zoo.dev

View File

@ -10,7 +10,7 @@ updates:
schedule:
interval: 'daily'
reviewers:
- franknoirot
- franknoirot
- irev-dev
- package-ecosystem: 'github-actions' # See documentation for possible values
directory: '/' # Location of package manifests
@ -26,10 +26,3 @@ updates:
reviewers:
- adamchalmers
- jessfraz
- package-ecosystem: 'cargo' # See documentation for possible values
directory: '/src-tauri/' # Location of package manifests
schedule:
interval: 'daily'
reviewers:
- adamchalmers
- jessfraz

View File

@ -0,0 +1,406 @@
name: build-test-publish-apps
on:
pull_request:
push:
branches:
- main
release:
types: [published]
schedule:
- cron: '0 4 * * *'
# Daily at 04:00 AM UTC
# Will checkout the last commit from the default branch (main as of 2023-10-04)
env:
CUT_RELEASE_PR: ${{ github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }}
BUILD_RELEASE: ${{ github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }}
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
prepare-json-files:
runs-on: ubuntu-22.04 # seperate job on Ubuntu for easy string manipulations (compared to Windows)
outputs:
version: ${{ steps.export_version.outputs.version }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Set nightly version
if: github.event_name == 'schedule'
run: |
VERSION=$(date +'%-y.%-m.%-d') yarn bump-jsons
# TODO: see if we need to inject updater nightly URL here https://dl.zoo.dev/releases/modeling-app/nightly/last_update.json
# TODO: see if we ned to add updater test URL here https://dl.zoo.dev/releases/modeling-app/updater-test/last_update.json
- uses: actions/upload-artifact@v3
if: ${{ github.event_name == 'schedule' || env.CUT_RELEASE_PR == 'true' }}
with:
path: |
package.json
- id: export_version
run: echo "version=`cat package.json | jq -r '.version'`" >> "$GITHUB_OUTPUT"
build-test-app-macos:
needs: [prepare-json-files]
runs-on: macos-14
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
if: github.event_name == 'schedule'
- name: Copy updated .json files
if: github.event_name == 'schedule'
run: |
ls -l artifact
cp artifact/package.json package.json
- name: Sync node version and setup cache
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn' # Set this to npm, yarn or pnpm.
- run: yarn install
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: Run build:wasm
run: "yarn build:wasm${{ env.BUILD_RELEASE == 'true' && '-dev' || ''}}"
# TODO: sign the app (and updater bundle potentially)
- name: Add signing certificate
if: ${{ env.BUILD_RELEASE == 'true' }}
run: chmod +x add-osx-cert.sh && ./add-osx-cert.sh
- name: Build the app for arm64
run: "yarn electron-forge make"
- name: Build the app for x64
run: "yarn electron-forge make --arch x64"
- name: List artifacts
run: "ls -R out/make"
# TODO: add the 'Build for Mac TestFlight (nightly)' stage back
- uses: actions/upload-artifact@v3
with:
path: "out/make/*/*/*/*"
build-test-app-windows:
needs: [prepare-json-files]
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
- name: Copy updated .json files
if: github.event_name == 'schedule'
run: |
ls -l artifact
cp artifact/package.json package.json
- name: Sync node version and setup cache
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn' # Set this to npm, yarn or pnpm.
- run: yarn install
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: Run build:wasm manually
shell: bash
env:
MODE: ${{ env.BUILD_RELEASE == 'true' && '--release' || '--debug' }}
run: |
mkdir src/wasm-lib/pkg; cd src/wasm-lib
echo "building with ${{ env.MODE }}"
npx wasm-pack build --target web --out-dir pkg ${{ env.MODE }}
cd ../../
cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
- name: Prepare certificate and variables (Windows only)
if: ${{ env.BUILD_RELEASE == 'true' }}
run: |
echo "${{secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12
cat /d/Certificate_pkcs12.p12
echo "::set-output name=version::${GITHUB_REF#refs/tags/v}"
echo "SM_HOST=${{ secrets.SM_HOST }}" >> "$GITHUB_ENV"
echo "SM_API_KEY=${{ secrets.SM_API_KEY }}" >> "$GITHUB_ENV"
echo "SM_CLIENT_CERT_FILE=D:\\Certificate_pkcs12.p12" >> "$GITHUB_ENV"
echo "SM_CLIENT_CERT_PASSWORD=${{ secrets.SM_CLIENT_CERT_PASSWORD }}" >> "$GITHUB_ENV"
echo "C:\Program Files (x86)\Windows Kits\10\App Certification Kit" >> $GITHUB_PATH
echo "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" >> $GITHUB_PATH
echo "C:\Program Files\DigiCert\DigiCert One Signing Manager Tools" >> $GITHUB_PATH
shell: bash
- name: Setup certicate with SSM KSP (Windows only)
if: ${{ env.BUILD_RELEASE == 'true' }}
run: |
curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o smtools-windows-x64.msi
msiexec /i smtools-windows-x64.msi /quiet /qn
smksp_registrar.exe list
smctl.exe keypair ls
C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user
smksp_cert_sync.exe
shell: cmd
- name: Build the app for x64
run: "yarn electron-forge make --arch x64"
- name: Build the app for arm64
run: "yarn electron-forge make --arch arm64"
- name: List artifacts
run: "ls -R out/make"
- name: Sign using Signtool
if: ${{ env.BUILD_RELEASE == 'true' }}
env:
THUMBPRINT: "F4C9A52FF7BC26EE5E054946F6B11DEEA94C748D"
X64_FILE: "D:\\a\\modeling-app\\modeling-app\\out\\make\\squirrel.windows\\x64\\Zoo Modeling App-*Setup.exe"
ARM64_FILE: "D:\\a\\modeling-app\\modeling-app\\out\\make\\squirrel.windows\\arm64\\Zoo Modeling App-*Setup.exe"
run: |
signtool.exe sign /sha1 ${{ env.THUMBPRINT }} /tr http://timestamp.digicert.com /td SHA256 /fd SHA256 "${{ env.X64_FILE }}"
signtool.exe verify /v /pa "${{ env.X64_FILE }}"
signtool.exe sign /sha1 ${{ env.THUMBPRINT }} /tr http://timestamp.digicert.com /td SHA256 /fd SHA256 "${{ env.ARM64_FILE }}"
signtool.exe verify /v /pa "${{ env.ARM64_FILE }}"
- uses: actions/upload-artifact@v3
with:
path: "out/make/*/*/*"
# TODO: Run e2e tests
build-test-app-ubuntu:
needs: [prepare-json-files]
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
if: github.event_name == 'schedule'
- name: Copy updated .json files
if: github.event_name == 'schedule'
run: |
ls -l artifact
cp artifact/package.json package.json
- name: Sync node version and setup cache
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn' # Set this to npm, yarn or pnpm.
- run: yarn install
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: Run build:wasm
run: "yarn build:wasm${{ env.BUILD_RELEASE == 'true' && '-dev' || ''}}"
- name: Build the app for arm64
run: "yarn electron-forge make --arch arm64"
- name: Build the app for x64
run: "yarn electron-forge make --arch x64"
- name: List artifacts
run: "ls -R out/make"
# TODO: add the 'Build for Mac TestFlight (nightly)' stage back
# TODO: sign the app (and updater bundle potentially)
- uses: actions/upload-artifact@v3
with:
path: "out/make/*/*/*"
publish-apps-release:
runs-on: ubuntu-22.04
permissions:
contents: write
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
needs: [prepare-json-files, build-test-app-macos, build-test-app-windows, build-test-app-ubuntu]
env:
VERSION_NO_V: ${{ needs.prepare-json-files.outputs.version }}
VERSION: ${{ github.event_name == 'release' && format('v{0}', needs.prepare-json-files.outputs.version) || needs.prepare-json-files.outputs.version }}
PUB_DATE: ${{ github.event_name == 'release' && github.event.release.created_at || github.event.repository.updated_at }}
NOTES: ${{ github.event_name == 'release' && github.event.release.body || format('Nightly build, commit {0}', github.sha) }}
BUCKET_DIR: ${{ github.event_name == 'release' && 'dl.kittycad.io/releases/modeling-app' || 'dl.kittycad.io/releases/modeling-app/nightly' }}
WEBSITE_DIR: ${{ github.event_name == 'release' && 'dl.zoo.dev/releases/modeling-app' || 'dl.zoo.dev/releases/modeling-app/nightly' }}
URL_CODED_NAME: ${{ github.event_name == 'schedule' && 'Zoo%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }}
steps:
- uses: actions/download-artifact@v3
- name: Generate the update static endpoint
run: |
ls -l artifact/*/*oo*
DARWIN_SIG=`cat artifact/macos/*.app.tar.gz.sig`
WINDOWS_X86_64_SIG=`cat artifact/msi/*x64*.msi.zip.sig`
WINDOWS_AARCH64_SIG=`cat artifact/msi/*arm64*.msi.zip.sig`
RELEASE_DIR=https://${WEBSITE_DIR}/${VERSION}
jq --null-input \
--arg version "${VERSION}" \
--arg pub_date "${PUB_DATE}" \
--arg notes "${NOTES}" \
--arg darwin_sig "$DARWIN_SIG" \
--arg darwin_url "$RELEASE_DIR/macos/${{ env.URL_CODED_NAME }}.app.tar.gz" \
--arg windows_x86_64_sig "$WINDOWS_X86_64_SIG" \
--arg windows_x86_64_url "$RELEASE_DIR/msi/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_x64_en-US.msi.zip" \
--arg windows_aarch64_sig "$WINDOWS_AARCH64_SIG" \
--arg windows_aarch64_url "$RELEASE_DIR/msi/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_arm64_en-US.msi.zip" \
'{
"version": $version,
"pub_date": $pub_date,
"notes": $notes,
"platforms": {
"darwin-x86_64": {
"signature": $darwin_sig,
"url": $darwin_url
},
"darwin-aarch64": {
"signature": $darwin_sig,
"url": $darwin_url
},
"windows-x86_64": {
"signature": $windows_x86_64_sig,
"url": $windows_x86_64_url
},
"windows-aarch64": {
"signature": $windows_aarch64_sig,
"url": $windows_aarch64_url
}
}
}' > last_update.json
cat last_update.json
- name: Generate the download static endpoint
run: |
RELEASE_DIR=https://${WEBSITE_DIR}/${VERSION}
jq --null-input \
--arg version "${VERSION}" \
--arg pub_date "${PUB_DATE}" \
--arg notes "${NOTES}" \
--arg darwin_url "$RELEASE_DIR/dmg/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_universal.dmg" \
--arg windows_x86_64_url "$RELEASE_DIR/msi/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_x64_en-US.msi" \
--arg windows_aarch64_url "$RELEASE_DIR/msi/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_arm64_en-US.msi" \
'{
"version": $version,
"pub_date": $pub_date,
"notes": $notes,
"platforms": {
"dmg-universal": {
"url": $darwin_url
},
"msi-x86_64": {
"url": $windows_x86_64_url
},
"msi-aarch64": {
"url": $windows_aarch64_url
}
}
}' > last_download.json
cat last_download.json
- name: Authenticate to Google Cloud
uses: 'google-github-actions/auth@v2.1.3'
with:
credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'
- name: Set up Google Cloud SDK
uses: google-github-actions/setup-gcloud@v2.1.0
with:
project_id: kittycadapi
- name: Upload release files to public bucket
uses: google-github-actions/upload-cloud-storage@v2.1.0
with:
path: artifact
glob: '*/Zoo*'
parent: false
destination: ${{ env.BUCKET_DIR }}/${{ env.VERSION }}
- name: Upload update endpoint to public bucket
uses: google-github-actions/upload-cloud-storage@v2.1.0
with:
path: last_update.json
destination: ${{ env.BUCKET_DIR }}
- name: Upload download endpoint to public bucket
uses: google-github-actions/upload-cloud-storage@v2.1.0
with:
path: last_download.json
destination: ${{ env.BUCKET_DIR }}
- name: Upload release files to Github
if: ${{ github.event_name == 'release' }}
uses: softprops/action-gh-release@v2
with:
files: 'artifact/*/Zoo*'
announce_release:
needs: [publish-apps-release]
runs-on: ubuntu-22.04
if: github.event_name == 'release'
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests
- name: Announce Release
env:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
RELEASE_VERSION: ${{ github.event.release.tag_name }}
RELEASE_BODY: ${{ github.event.release.body}}
run: python public/announce_release.py

115
.github/workflows/build-test-web.yml vendored Normal file
View File

@ -0,0 +1,115 @@
name: build-test-web
on:
pull_request:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: write
pull-requests: write
actions: read
jobs:
check-format:
runs-on: 'ubuntu-22.04'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- run: yarn fmt-check
check-types:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- run: yarn build:wasm
- run: yarn xstate:typegen
- run: yarn tsc
check-typos:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
- name: Install codespell
run: |
python -m pip install codespell
- name: Run codespell
run: codespell --config .codespellrc # Edit this file to tweak the typo list and other configuration.
build-test-web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- run: yarn build:wasm
- run: yarn simpleserver:ci
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
- name: Install Chromium Browser
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
run: yarn playwright install chromium --with-deps
- name: run unit tests
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
run: yarn test:nowatch
env:
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
- name: check for changes
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
id: git-check
run: |
git add src/lang/std/artifactMapGraphs
if git status src/lang/std/artifactMapGraphs | grep -q "Changes to be committed"
then echo "modified=true" >> $GITHUB_OUTPUT
else echo "modified=false" >> $GITHUB_OUTPUT
fi
- name: Commit changes, if any
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' && steps.git-check.outputs.modified == 'true' }}
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
git fetch origin
echo ${{ github.head_ref }}
git checkout ${{ github.head_ref }}
# TODO when webkit works on ubuntu remove the os part of the commit message
git commit -am "Look at this (photo)Graph *in the voice of Nickelback*" || true
git push
git push origin ${{ github.head_ref }}

View File

@ -25,7 +25,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
dir: ['src/wasm-lib', 'src-tauri']
dir: ['src/wasm-lib']
steps:
- uses: actions/checkout@v4
- name: Install latest rust
@ -35,24 +35,6 @@ jobs:
override: true
components: clippy
- name: install dependencies
if: matrix.dir == 'src-tauri'
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libayatana-appindicator3-dev \
webkit2gtk-driver \
libsoup-3.0-dev \
libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.1-dev \
at-spi2-core \
xvfb
yarn install
yarn build:wasm
yarn build:local
- name: Rust Cache
uses: Swatinem/rust-cache@v2.6.1

View File

@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
dir: ['src/wasm-lib', 'src-tauri']
dir: ['src/wasm-lib']
steps:
- uses: actions/checkout@v4
- name: Install latest rust

View File

@ -1,57 +0,0 @@
on:
push:
branches:
- main
paths:
- 'src-tauri/**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-test-tauri.yml
pull_request:
paths:
- 'src-tauri/**.rs'
- '**/Cargo.toml'
- '**/Cargo.lock'
- '**/rust-toolchain.toml'
- .github/workflows/cargo-test-tauri.yml
workflow_dispatch:
permissions: read-all
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
name: cargo test of tauri
jobs:
cargotest:
name: cargo test
runs-on: ubuntu-latest-8-cores
strategy:
matrix:
dir: ['src-tauri']
steps:
- uses: actions/checkout@v4
- name: Install latest rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: install dependencies
if: matrix.dir == 'src-tauri'
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libayatana-appindicator3-dev \
webkit2gtk-driver \
libsoup-3.0-dev \
libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.1-dev \
at-spi2-core \
xvfb
- name: Rust Cache
uses: Swatinem/rust-cache@v2.6.1
- name: cargo test
shell: bash
run: |-
cd "${{ matrix.dir }}"
cargo test --all

View File

@ -1,586 +0,0 @@
name: CI
on:
pull_request:
push:
branches:
- main
release:
types: [published]
schedule:
- cron: '0 4 * * *'
# Daily at 04:00 AM UTC
# Will checkout the last commit from the default branch (main as of 2023-10-04)
env:
CUT_RELEASE_PR: ${{ github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }}
BUILD_RELEASE: ${{ github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'pull_request' && (contains(github.event.pull_request.title, 'Cut release v')) }}
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
contents: write
pull-requests: write
actions: read
jobs:
check-format:
runs-on: 'ubuntu-latest'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- run: yarn fmt-check
check-types:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- run: yarn build:wasm
- run: yarn xstate:typegen
- run: yarn tsc
check-typos:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
- name: Install codespell
run: |
python -m pip install codespell
- name: Run codespell
run: codespell --config .codespellrc # Edit this file to tweak the typo list and other configuration.
build-test-web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- run: yarn install
- uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- run: yarn build:wasm
- run: yarn simpleserver:ci
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
- name: Install Chromium Browser
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
run: yarn playwright install chromium --with-deps
- name: run unit tests
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
run: yarn test:nowatch
env:
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
- name: check for changes
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
id: git-check
run: |
git add src/lang/std/artifactMapGraphs
if git status src/lang/std/artifactMapGraphs | grep -q "Changes to be committed"
then echo "modified=true" >> $GITHUB_OUTPUT
else echo "modified=false" >> $GITHUB_OUTPUT
fi
- name: Commit changes, if any
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' && steps.git-check.outputs.modified == 'true' }}
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
git fetch origin
echo ${{ github.head_ref }}
git checkout ${{ github.head_ref }}
# TODO when webkit works on ubuntu remove the os part of the commit message
git commit -am "Look at this (photo)Graph *in the voice of Nickelback*" || true
git push
git push origin ${{ github.head_ref }}
prepare-json-files:
runs-on: ubuntu-latest # seperate job on Ubuntu for easy string manipulations (compared to Windows)
outputs:
version: ${{ steps.export_version.outputs.version }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Set nightly version
if: github.event_name == 'schedule'
run: |
VERSION=$(date +'%-y.%-m.%-d') yarn bump-jsons
echo "$(jq --arg url 'https://dl.zoo.dev/releases/modeling-app/nightly/last_update.json' \
'.plugins.updater.endpoints[]=$url' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
echo "$(jq --arg id 'dev.zoo.modeling-app-nightly' \
'.identifier=$id' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
echo "$(jq --arg name 'Zoo Modeling App (Nightly)' \
'.productName=$name' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
- name: Set updater test version
if: ${{ env.CUT_RELEASE_PR == 'true' }}
run: |
echo "$(jq --arg url 'https://dl.zoo.dev/releases/modeling-app/test/last_update.json' \
'.plugins.updater.endpoints[]=$url' src-tauri/tauri.release.conf.json --indent 2)" > src-tauri/tauri.release.conf.json
- uses: actions/upload-artifact@v3
if: ${{ github.event_name == 'schedule' || env.CUT_RELEASE_PR == 'true' }}
with:
path: |
package.json
src-tauri/tauri.conf.json
src-tauri/tauri.release.conf.json
- id: export_version
run: echo "version=`cat package.json | jq -r '.version'`" >> "$GITHUB_OUTPUT"
build-test-apps:
needs: [prepare-json-files]
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-14, ubuntu-latest, windows-latest]
env:
# Specific Apple Universal target for macos
TAURI_ARGS_MACOS: ${{ matrix.os == 'macos-14' && '--target universal-apple-darwin' || '' }}
# Only build executable on linux (no appimage or deb)
TAURI_ARGS_UBUNTU: ${{ matrix.os == 'ubuntu-latest' && '--bundles' || '' }}
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v3
if: github.event_name == 'schedule'
- name: Copy updated .json files
if: github.event_name == 'schedule'
run: |
ls -l artifact
cp artifact/package.json package.json
cp artifact/src-tauri/tauri.conf.json src-tauri/tauri.conf.json
cp artifact/src-tauri/tauri.release.conf.json src-tauri/tauri.release.conf.json
- name: Update WebView2 on Windows
if: matrix.os == 'windows-latest'
# Workaround needed to build the tauri windows app with matching edge version.
# From https://github.com/actions/runner-images/issues/9538
run: |
Invoke-WebRequest -Uri 'https://go.microsoft.com/fwlink/p/?LinkId=2124703' -OutFile 'setup.exe'
Start-Process -FilePath setup.exe -Verb RunAs -Wait
- name: Install ubuntu system dependencies
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libayatana-appindicator3-dev \
webkit2gtk-driver \
libsoup-3.0-dev \
libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.1-dev \
at-spi2-core \
xvfb
- name: Sync node version and setup cache
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn' # Set this to npm, yarn or pnpm.
- run: yarn install
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Setup Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: './src-tauri -> target'
- uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: Run build:wasm manually
shell: bash
env:
MODE: ${{ env.BUILD_RELEASE == 'true' && '--release' || '--debug' }}
run: |
mkdir src/wasm-lib/pkg; cd src/wasm-lib
echo "building with ${{ env.MODE }}"
npx wasm-pack build --target web --out-dir pkg ${{ env.MODE }}
cd ../../
cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
- name: Run vite build (build:both)
run: yarn vite build --mode ${{ env.BUILD_RELEASE == 'true' && 'production' || 'development' }}
- name: Fix format
run: yarn fmt
- name: Install x86 target for Universal builds (MacOS only)
if: matrix.os == 'macos-14'
run: |
rustup target add x86_64-apple-darwin
- name: Prepare certificate and variables (Windows only)
if: ${{ matrix.os == 'windows-latest' && env.BUILD_RELEASE == 'true' }}
run: |
echo "${{secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12
cat /d/Certificate_pkcs12.p12
echo "::set-output name=version::${GITHUB_REF#refs/tags/v}"
echo "SM_HOST=${{ secrets.SM_HOST }}" >> "$GITHUB_ENV"
echo "SM_API_KEY=${{ secrets.SM_API_KEY }}" >> "$GITHUB_ENV"
echo "SM_CLIENT_CERT_FILE=D:\\Certificate_pkcs12.p12" >> "$GITHUB_ENV"
echo "SM_CLIENT_CERT_PASSWORD=${{ secrets.SM_CLIENT_CERT_PASSWORD }}" >> "$GITHUB_ENV"
echo "C:\Program Files (x86)\Windows Kits\10\App Certification Kit" >> $GITHUB_PATH
echo "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools" >> $GITHUB_PATH
echo "C:\Program Files\DigiCert\DigiCert One Signing Manager Tools" >> $GITHUB_PATH
shell: bash
- name: Setup certicate with SSM KSP (Windows only)
if: ${{ matrix.os == 'windows-latest' && env.BUILD_RELEASE == 'true' }}
run: |
curl -X GET https://one.digicert.com/signingmanager/api-ui/v1/releases/smtools-windows-x64.msi/download -H "x-api-key:%SM_API_KEY%" -o smtools-windows-x64.msi
msiexec /i smtools-windows-x64.msi /quiet /qn
smksp_registrar.exe list
smctl.exe keypair ls
C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user
smksp_cert_sync.exe
shell: cmd
- name: Build the app (debug)
if: ${{ env.BUILD_RELEASE == 'false' }}
run: "yarn tauri build --debug ${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}"
- name: Build for Mac TestFlight (nightly)
if: ${{ github.event_name == 'schedule' && matrix.os == 'macos-14' }}
shell: bash
run: |
unset APPLE_SIGNING_IDENTITY
unset APPLE_CERTIFICATE
sign_app="3rd Party Mac Developer Application: KittyCAD Inc (${APPLE_TEAM_ID})"
sign_install="3rd Party Mac Developer Installer: KittyCAD Inc (${APPLE_TEAM_ID})"
profile="src-tauri/entitlements/Mac_App_Distribution.provisionprofile"
mkdir -p src-tauri/entitlements
echo -n "${APPLE_STORE_PROVISIONING_PROFILE}" | base64 --decode -o "${profile}"
echo -n "${APPLE_STORE_DISTRIBUTION_CERT}" | base64 --decode -o "dist.cer"
echo -n "${APPLE_STORE_INSTALLER_CERT}" | base64 --decode -o "installer.cer"
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
KEYCHAIN_PASSWORD="password"
# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# import certificate to keychain
security import "dist.cer" -P "$APPLE_STORE_P12_PASSWORD" -k $KEYCHAIN_PATH -f pkcs12 -t cert -A
security import "installer.cer" -P "$APPLE_STORE_P12_PASSWORD" -k $KEYCHAIN_PATH -f pkcs12 -t cert -A
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
target="universal-apple-darwin"
# Turn off the default target
# We don't want to install the updater for the apple store build
sed -i.bu "s/default =/# default =/" src-tauri/Cargo.toml
rm src-tauri/Cargo.toml.bu
git diff src-tauri/Cargo.toml
yarn tauri build --target "${target}" --verbose --config src-tauri/tauri.app-store.conf.json
app_path="src-tauri/target/${target}/release/bundle/macos/Zoo Modeling App.app"
build_name="src-tauri/target/${target}/release/bundle/macos/Zoo Modeling App.pkg"
cp_dir="src-tauri/target/${target}/release/bundle/macos/Zoo Modeling App.app/Contents/embedded.provisionprofile"
entitlements="src-tauri/entitlements/app-store.entitlements"
cp "${profile}" "${cp_dir}"
codesign --deep --force -s "${sign_app}" --entitlements "${entitlements}" "${app_path}"
productbuild --component "${app_path}" /Applications/ --sign "${sign_install}" "${build_name}"
# Undo the changes to the Cargo.toml
git checkout src-tauri/Cargo.toml
env:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_STORE_PROVISIONING_PROFILE: ${{ secrets.APPLE_STORE_PROVISIONING_PROFILE }}
APPLE_STORE_DISTRIBUTION_CERT: ${{ secrets.APPLE_STORE_DISTRIBUTION_CERT }}
APPLE_STORE_INSTALLER_CERT: ${{ secrets.APPLE_STORE_INSTALLER_CERT }}
APPLE_STORE_P12_PASSWORD: ${{ secrets.APPLE_STORE_P12_PASSWORD }}
- name: 'Upload to Mac TestFlight (nightly)'
uses: apple-actions/upload-testflight-build@v1
if: ${{ github.event_name == 'schedule' && matrix.os == 'macos-14' }}
with:
app-path: 'src-tauri/target/universal-apple-darwin/release/bundle/macos/Zoo Modeling App.pkg'
issuer-id: ${{ secrets.APPLE_STORE_ISSUER_ID }}
api-key-id: ${{ secrets.APPLE_STORE_API_KEY_ID }}
api-private-key: ${{ secrets.APPLE_STORE_API_PRIVATE_KEY }}
app-type: osx
- name: Clean up after Mac TestFlight (nightly)
if: ${{ github.event_name == 'schedule' && matrix.os == 'macos-14' }}
shell: bash
run: |
git status
# remove our target builds because we want to make sure the later build
# includes the updater, and that anything we changed with the target
# does not persist
rm -rf src-tauri/target
# Lets get rid of the info.plist for the normal mac builds since its
# being sketchy.
rm src-tauri/Info.plist
# We do this after the apple store because the apple store build is
# specific and we want to overwrite it with the this new build after and
# not upload the apple store build to the public bucket
- name: Build the app (release) and sign
if: ${{ env.BUILD_RELEASE == 'true' }}
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
TAURI_CONF_ARGS: "--config ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}"
run: "yarn tauri build ${{ env.TAURI_CONF_ARGS }} ${{ env.TAURI_ARGS_MACOS }} ${{ env.TAURI_ARGS_UBUNTU }}"
- uses: actions/upload-artifact@v3
if: matrix.os != 'ubuntu-latest'
env:
PREFIX: ${{ matrix.os == 'macos-14' && 'src-tauri/target/universal-apple-darwin' || 'src-tauri/target' }}
MODE: ${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}
with:
path: "${{ env.PREFIX }}/${{ env.MODE }}/bundle/*/*"
- name: Run e2e tests (linux only)
if: ${{ matrix.os == 'ubuntu-latest' && github.event_name != 'release' && github.event_name != 'schedule' }}
run: |
cargo install tauri-driver --force
source .env.${{ env.BUILD_RELEASE == 'true' && 'production' || 'development' }}
export VITE_KC_API_BASE_URL
xvfb-run yarn test:e2e:tauri
env:
E2E_APPLICATION: "./src-tauri/target/${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}/zoo-modeling-app"
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
- name: Run e2e tests (windows only)
if: ${{ matrix.os == 'windows-latest' && github.event_name != 'release' && github.event_name != 'schedule' }}
run: |
cargo install tauri-driver --force
yarn wdio run wdio.conf.ts
env:
E2E_APPLICATION: ".\\src-tauri\\target\\${{ env.BUILD_RELEASE == 'true' && 'release' || 'debug' }}\\Zoo Modeling App.exe"
KITTYCAD_API_TOKEN: ${{ env.BUILD_RELEASE == 'true' && secrets.KITTYCAD_API_TOKEN || secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_API_BASE_URL: ${{ env.BUILD_RELEASE == 'true' && 'https://api.zoo.dev' || 'https://api.dev.zoo.dev' }}
E2E_TAURI_ENABLED: true
TS_NODE_COMPILER_OPTIONS: '{"module": "commonjs"}'
- uses: actions/download-artifact@v3
if: ${{ env.CUT_RELEASE_PR == 'true' }}
- name: Copy updated .json file for updater test
if: ${{ env.CUT_RELEASE_PR == 'true' }}
run: |
ls -l artifact
cp artifact/src-tauri/tauri.release.conf.json src-tauri/tauri.release.conf.json
cat src-tauri/tauri.release.conf.json
- name: Build the app (release, updater test)
if: ${{ env.CUT_RELEASE_PR == 'true' && matrix.os != 'ubuntu-latest' }}
env:
TAURI_CONF_ARGS: "-c ${{ matrix.os == 'windows-latest' && 'src-tauri\\tauri.release.conf.json' || 'src-tauri/tauri.release.conf.json' }}"
TAURI_BUNDLE_ARGS: "-b ${{ matrix.os == 'windows-latest' && 'msi' || 'dmg' }}"
run: "yarn tauri build ${{ env.TAURI_CONF_ARGS }} ${{ env.TAURI_BUNDLE_ARGS }} ${{ env.TAURI_ARGS_MACOS }}"
- uses: actions/upload-artifact@v3
if: ${{ env.CUT_RELEASE_PR == 'true' && matrix.os != 'ubuntu-latest' }}
with:
path: "${{ matrix.os == 'macos-14' && 'src-tauri/target/universal-apple-darwin/release/bundle/dmg/*.dmg' || 'src-tauri/target/release/bundle/msi/*.msi' }}"
name: updater-test
publish-apps-release:
permissions:
contents: write
runs-on: ubuntu-latest
if: ${{ github.event_name == 'release' || github.event_name == 'schedule' }}
needs: [check-format, check-types, check-typos, build-test-web, prepare-json-files, build-test-apps]
env:
VERSION_NO_V: ${{ needs.prepare-json-files.outputs.version }}
VERSION: ${{ github.event_name == 'release' && format('v{0}', needs.prepare-json-files.outputs.version) || needs.prepare-json-files.outputs.version }}
PUB_DATE: ${{ github.event_name == 'release' && github.event.release.created_at || github.event.repository.updated_at }}
NOTES: ${{ github.event_name == 'release' && github.event.release.body || format('Nightly build, commit {0}', github.sha) }}
BUCKET_DIR: ${{ github.event_name == 'release' && 'dl.kittycad.io/releases/modeling-app' || 'dl.kittycad.io/releases/modeling-app/nightly' }}
WEBSITE_DIR: ${{ github.event_name == 'release' && 'dl.zoo.dev/releases/modeling-app' || 'dl.zoo.dev/releases/modeling-app/nightly' }}
URL_CODED_NAME: ${{ github.event_name == 'schedule' && 'Zoo%20Modeling%20App%20%28Nightly%29' || 'Zoo%20Modeling%20App' }}
steps:
- uses: actions/download-artifact@v3
- name: Generate the update static endpoint
run: |
ls -l artifact/*/*oo*
DARWIN_SIG=`cat artifact/macos/*.app.tar.gz.sig`
WINDOWS_SIG=`cat artifact/msi/*.msi.zip.sig`
RELEASE_DIR=https://${WEBSITE_DIR}/${VERSION}
jq --null-input \
--arg version "${VERSION}" \
--arg pub_date "${PUB_DATE}" \
--arg notes "${NOTES}" \
--arg darwin_sig "$DARWIN_SIG" \
--arg darwin_url "$RELEASE_DIR/macos/${{ env.URL_CODED_NAME }}.app.tar.gz" \
--arg windows_sig "$WINDOWS_SIG" \
--arg windows_url "$RELEASE_DIR/msi/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_x64_en-US.msi.zip" \
'{
"version": $version,
"pub_date": $pub_date,
"notes": $notes,
"platforms": {
"darwin-x86_64": {
"signature": $darwin_sig,
"url": $darwin_url
},
"darwin-aarch64": {
"signature": $darwin_sig,
"url": $darwin_url
},
"windows-x86_64": {
"signature": $windows_sig,
"url": $windows_url
}
}
}' > last_update.json
cat last_update.json
- name: Generate the download static endpoint
run: |
RELEASE_DIR=https://${WEBSITE_DIR}/${VERSION}
jq --null-input \
--arg version "${VERSION}" \
--arg pub_date "${PUB_DATE}" \
--arg notes "${NOTES}" \
--arg darwin_url "$RELEASE_DIR/dmg/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_universal.dmg" \
--arg windows_url "$RELEASE_DIR/msi/${{ env.URL_CODED_NAME }}_${VERSION_NO_V}_x64_en-US.msi" \
'{
"version": $version,
"pub_date": $pub_date,
"notes": $notes,
"platforms": {
"dmg-universal": {
"url": $darwin_url
},
"msi-x86_64": {
"url": $windows_url
}
}
}' > last_download.json
cat last_download.json
- name: Authenticate to Google Cloud
uses: 'google-github-actions/auth@v2.1.3'
with:
credentials_json: '${{ secrets.GOOGLE_CLOUD_DL_SA }}'
- name: Set up Google Cloud SDK
uses: google-github-actions/setup-gcloud@v2.1.0
with:
project_id: kittycadapi
- name: Upload release files to public bucket
uses: google-github-actions/upload-cloud-storage@v2.1.1
with:
path: artifact
glob: '*/Zoo*'
parent: false
destination: ${{ env.BUCKET_DIR }}/${{ env.VERSION }}
- name: Upload update endpoint to public bucket
uses: google-github-actions/upload-cloud-storage@v2.1.1
with:
path: last_update.json
destination: ${{ env.BUCKET_DIR }}
- name: Upload download endpoint to public bucket
uses: google-github-actions/upload-cloud-storage@v2.1.1
with:
path: last_download.json
destination: ${{ env.BUCKET_DIR }}
- name: Upload release files to Github
if: ${{ github.event_name == 'release' }}
uses: softprops/action-gh-release@v2
with:
files: 'artifact/*/Zoo*'
announce_release:
needs: [publish-apps-release]
runs-on: ubuntu-latest
if: github.event_name == 'release'
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests
- name: Announce Release
env:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
RELEASE_VERSION: ${{ github.event.release.tag_name }}
RELEASE_BODY: ${{ github.event.release.body}}
run: python public/announce_release.py

View File

@ -6,7 +6,7 @@ on:
branches: [ main ]
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
permissions:
@ -33,14 +33,15 @@ jobs:
rust:
- 'src/wasm-lib/**'
playwright-ubuntu:
timeout-minutes: 30
runs-on: ubuntu-latest
playwright-chrome:
timeout-minutes: ${{ matrix.os == 'macos-14' && 60 || 40 }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
runs-on: ${{ matrix.os }}
needs: check-rust-changes
steps:
- name: Tune GitHub-hosted runner network
@ -52,6 +53,7 @@ jobs:
cache: 'yarn'
- uses: KittyCAD/action-install-cli@main
- name: Install dependencies
shell: bash
run: yarn
- name: Cache Playwright Browsers
uses: actions/cache@v4
@ -60,6 +62,7 @@ jobs:
~/.cache/ms-playwright/
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Browsers
shell: bash
run: yarn playwright install --with-deps
- name: Download Wasm Cache
id: download-wasm
@ -74,6 +77,7 @@ jobs:
path: src/wasm-lib/pkg
- name: copy wasm blob
if: needs.check-rust-changes.outputs.rust-changed == 'false'
shell: bash
run: cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
continue-on-error: true
- name: Setup Rust
@ -88,7 +92,15 @@ jobs:
uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: install good sed
if: ${{ startsWith(matrix.os, 'macos') }}
shell: bash
run: |
brew install gnu-sed
echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH
- name: Install vector
shell: bash
if: ${{ !startsWith(matrix.os, 'windows') }}
run: |
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
chmod +x /tmp/vector.sh
@ -104,31 +116,39 @@ jobs:
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
- name: Build Wasm (because rust diff)
if: needs.check-rust-changes.outputs.rust-changed == 'true'
shell: bash
run: yarn build:wasm
- name: OR Build Wasm (because wasm cache failed)
if: steps.download-wasm.outcome == 'failure'
shell: bash
run: yarn build:wasm
- name: build web
run: yarn build:local
shell: bash
- name: Run ubuntu/chrome snapshots
shell: bash
run: |
yarn playwright test --project="Google Chrome" --config=playwright.ci.config.ts --retries="3" --update-snapshots --grep=@snapshot --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
env:
CI: true
NODE_ENV: development
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_SKIP_AUTH: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
snapshottoken: ${{ secrets.KITTYCAD_API_TOKEN }}
- uses: actions/upload-artifact@v4
if: always()
if: ${{ !cancelled() && (success() || failure()) }}
with:
name: playwright-report-ubuntu-snapshot-${{ matrix.shardIndex }}-${{ github.sha }}
path: playwright-report/
retention-days: 30
overwrite: true
- name: Clean up test-results
if: always()
if: ${{ !cancelled() && (success() || failure()) }}
continue-on-error: true
run: rm -r test-results
- name: check for changes
shell: bash
id: git-check
run: |
git add .
@ -138,6 +158,7 @@ jobs:
fi
- name: Commit changes, if any
if: steps.git-check.outputs.modified == 'true'
shell: bash
run: |
git add .
git config --local user.email "github-actions[bot]@users.noreply.github.com"
@ -146,8 +167,7 @@ jobs:
git fetch origin
echo ${{ github.head_ref }}
git checkout ${{ github.head_ref }}
# TODO when webkit works on ubuntu remove the os part of the commit message
git commit -am "A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)" || true
git commit -am "A snapshot a day keeps the bugs away! 📷🐛 (OS: ${{matrix.os}})" || true
git push
git push origin ${{ github.head_ref }}
# only upload artifacts if there's actually changes
@ -157,21 +177,21 @@ jobs:
name: playwright-report-ubuntu-${{ matrix.shardIndex }}-${{ github.sha }}
path: playwright-report/
retention-days: 30
# if have previous run results, use them
- uses: actions/download-artifact@v4
if: always()
if: ${{ !cancelled() && (success() || failure()) }}
continue-on-error: true
with:
name: test-results-ubuntu-${{ matrix.shardIndex }}-${{ github.sha }}
path: test-results/
- name: Run ubuntu/chrome flow (with retries)
- name: Run playwright/chrome flow (with retries)
id: retry
if: always()
if: ${{ !cancelled() && (success() || failure()) }}
shell: bash
run: |
if [[ ! -f "test-results/.last-run.json" ]]; then
# if no last run artifact, than run plawright normally
echo "run playwright normally"
yarn playwright test --project="Google Chrome" --config=playwright.ci.config.ts --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --grep-invert=@snapshot || true
yarn playwright test --project="Google Chrome" --config=playwright.ci.config.ts --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --grep-invert="@snapshot|@electron" || true
# # send to axiom
node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1
fi
@ -186,7 +206,7 @@ jobs:
if [[ $failed_tests -gt 0 ]]; then
echo "retried=true" >>$GITHUB_OUTPUT
echo "run playwright with last failed tests and retry $retry"
yarn playwright test --project="Google Chrome" --config=playwright.ci.config.ts --last-failed --grep-invert=@snapshot || true
yarn playwright test --project="Google Chrome" --config=playwright.ci.config.ts --last-failed --grep-invert="@snapshot|@electron" || true
# send to axiom
node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1
retry=$((retry + 1))
@ -212,6 +232,9 @@ jobs:
exit 0
env:
CI: true
NODE_ENV: development
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_SKIP_AUTH: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
- name: send to axiom
if: always()
@ -233,14 +256,14 @@ jobs:
retention-days: 30
overwrite: true
playwright-macos:
timeout-minutes: 30
runs-on: macos-14
playwright-electron:
strategy:
fail-fast: false
matrix:
shardIndex: [1, 2, 3, 4]
shardTotal: [4]
os: [ubuntu-latest, windows-latest, macos-14]
timeout-minutes: 30
runs-on: ${{ matrix.os }}
needs: check-rust-changes
steps:
- name: Tune GitHub-hosted runner network
@ -250,18 +273,19 @@ jobs:
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- uses: KittyCAD/action-install-cli@main
- name: Install dependencies
shell: bash
run: yarn
- name: Cache Playwright Browsers
uses: actions/cache@v4
with:
path: |
~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-playwright-
~/.cache/ms-playwright/
key: ${{ runner.os }}-playwright-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
shell: bash
run: yarn playwright install chromium --with-deps
- name: Download Wasm Cache
id: download-wasm
if: needs.check-rust-changes.outputs.rust-changed == 'false'
@ -275,6 +299,7 @@ jobs:
path: src/wasm-lib/pkg
- name: copy wasm blob
if: needs.check-rust-changes.outputs.rust-changed == 'false'
shell: bash
run: cp src/wasm-lib/pkg/wasm_lib_bg.wasm public
continue-on-error: true
- name: Setup Rust
@ -289,49 +314,64 @@ jobs:
uses: Swatinem/rust-cache@v2
with:
workspaces: './src/wasm-lib'
- name: install good sed
if: ${{ startsWith(matrix.os, 'macos') }}
shell: bash
run: |
brew install gnu-sed
echo "/opt/homebrew/opt/gnu-sed/libexec/gnubin" >> $GITHUB_PATH
- name: Install vector
if: ${{ !startsWith(matrix.os, 'windows') }}
shell: bash
run: |
curl --proto '=https' --tlsv1.2 -sSfL https://sh.vector.dev > /tmp/vector.sh
chmod +x /tmp/vector.sh
/tmp/vector.sh -y -no-modify-path
mkdir -p /tmp/vector
cp .github/workflows/vector.toml /tmp/vector.toml
sed -i "" "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
sed -i "" "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
sed -i "" "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
sed -i "" "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
sed -i "" "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml
sed -i "s#GITHUB_WORKFLOW#${GITHUB_WORKFLOW}#g" /tmp/vector.toml
sed -i "s#GITHUB_REPOSITORY#${GITHUB_REPOSITORY}#g" /tmp/vector.toml
sed -i "s#GITHUB_SHA#${GITHUB_SHA}#g" /tmp/vector.toml
sed -i "s#GITHUB_REF_NAME#${GITHUB_REF_NAME}#g" /tmp/vector.toml
sed -i "s#GH_ACTIONS_AXIOM_TOKEN#${{secrets.GH_ACTIONS_AXIOM_TOKEN}}#g" /tmp/vector.toml
cat /tmp/vector.toml
${HOME}/.vector/bin/vector --config /tmp/vector.toml &
- name: Build Wasm (because rust diff)
if: needs.check-rust-changes.outputs.rust-changed == 'true'
shell: bash
run: yarn build:wasm
- name: OR Build Wasm (because wasm cache failed)
if: steps.download-wasm.outcome == 'failure'
shell: bash
run: yarn build:wasm
- name: build web
run: yarn build:local
# if have previous run results, use them
- name: build electron
shell: bash
run: yarn electron:package
- uses: actions/download-artifact@v4
if: ${{ always() }}
if: ${{ !cancelled() && (success() || failure()) }}
continue-on-error: true
with:
name: test-results-macos-${{ matrix.shardIndex }}-${{ github.sha }}
name: test-results-ubuntu-${{ github.sha }}
path: test-results/
- name: Run macos/safari flow (with retries)
- name: Run electron tests (with retries)
id: retry
if: always()
if: ${{ !cancelled() && (success() || failure()) }}
shell: bash
run: |
if [[ ! -f "test-results/.last-run.json" ]]; then
# if no last run artifact, than run plawright normally
echo "run playwright normally"
yarn playwright test --project="webkit" --config=playwright.ci.config.ts --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} --grep-invert=@snapshot || true
if [[ "$IS_UBUNTU" == "true" ]]; then
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn playwright test --config=playwright.electron.config.ts --grep=@electron || true
else
yarn playwright test --config=playwright.electron.config.ts --grep=@electron || true
fi
# # send to axiom
node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1
fi
retry=1
max_retrys=4
max_retrys=2
# retry failed tests, doing our own retries because using inbuilt playwright retries causes connection issues
while [[ $retry -le $max_retrys ]]; do
@ -340,7 +380,11 @@ jobs:
if [[ $failed_tests -gt 0 ]]; then
echo "retried=true" >>$GITHUB_OUTPUT
echo "run playwright with last failed tests and retry $retry"
yarn playwright test --project="webkit" --config=playwright.ci.config.ts --last-failed --grep-invert=@snapshot || true
if [[ "$IS_UBUNTU" == "true" ]]; then
xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- yarn playwright test --config=playwright.electron.config.ts --grep=@electron || true
else
yarn playwright test --config=playwright.electron.config.ts --grep=@electron || true
fi
# send to axiom
node playwrightProcess.mjs | tee /tmp/github-actions.log > /dev/null 2>&1
retry=$((retry + 1))
@ -366,18 +410,27 @@ jobs:
exit 0
env:
CI: true
token: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
NODE_ENV: development
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
VITE_KC_SKIP_AUTH: true
IS_UBUNTU: ${{ startsWith(matrix.os, 'ubuntu') && 'true' || 'false' }}
#DEBUG: 'pw:browser*'
- name: send to axiom
if: ${{ !cancelled() && (success() || failure()) && !startsWith(matrix.os, 'windows') }}
shell: bash
run: |
node playwrightProcess.mjs | tee /tmp/github-actions.log
- uses: actions/upload-artifact@v4
if: ${{ always() }}
if: ${{ !cancelled() && (success() || failure()) }}
with:
name: test-results-macos-${{ matrix.shardIndex }}-${{ github.sha }}
name: test-results-electron-${{ github.sha }}
path: test-results/
retention-days: 30
overwrite: true
- uses: actions/upload-artifact@v4
if: ${{ always() }}
if: ${{ !cancelled() && (success() || failure()) }}
with:
name: playwright-report-macos-${{ matrix.shardIndex }}-${{ github.sha }}
name: playwright-report-electron-${{ github.sha }}
path: playwright-report/
retention-days: 30
overwrite: true

8
.gitignore vendored
View File

@ -62,3 +62,11 @@ Mac_App_Distribution.provisionprofile
*.tsbuildinfo
venv
.vite/
# electron
out/
src-tauri/target
electron-test-projects-dir
electron-test-projects-dir-2

View File

@ -89,26 +89,19 @@ enable third-party cookies. You can enable third-party cookies by clicking on
the eye with a slash through it in the URL bar, and clicking on "Enable
Third-Party Cookies".
## Tauri
## Desktop
To spin up up tauri dev, `yarn install` and `yarn build:wasm-dev` need to have been done before hand then
To spin up the desktop app, `yarn install` and `yarn build:wasm-dev` need to have been done before hand then
```
yarn tauri dev
yarn electron:start
```
Will spin up the web app before opening up the tauri dev desktop app. Note that it's probably a good idea to close the browser tab that gets opened since at the time of writing they can conflict.
This will start the application and hot-reload on changed.
The dev instance automatically opens up the browser devtools which can be disabled by [commenting it out](https://github.com/KittyCAD/modeling-app/blob/main/src-tauri/src/main.rs#L92.)
Devtools can be opened with the usual Cmd/Ctrl-Shift-I.
To build, run `yarn tauri build`, or `yarn tauri build --debug` to keep access to the devtools.
Note that these became separate apps on Macos, so make sure you open the right one after a build 😉
![image](https://github.com/KittyCAD/modeling-app/assets/29681384/a08762c5-8d16-42d8-a02f-a5efc9ae5551)
<img width="1232" alt="image" src="https://user-images.githubusercontent.com/29681384/211947063-46164bb4-7bdd-45cb-9a76-2f40c71a24aa.png">
<img width="1232" alt="image (1)" src="https://user-images.githubusercontent.com/29681384/211947073-e76b4933-bef5-4636-bc4d-e930ac8e290f.png">
To build, run `yarn electron:package`.
## Checking out commits / Bisecting

24
add-osx-cert.sh Normal file
View File

@ -0,0 +1,24 @@
#!/usr/bin/env sh
# From https://dev.to/rwwagner90/signing-electron-apps-with-github-actions-4cof
KEY_CHAIN=build.keychain
CERTIFICATE_P12=certificate.p12
# Recreate the certificate from the secure environment variable
echo $APPLE_CERTIFICATE | base64 --decode > $CERTIFICATE_P12
#create a keychain
security create-keychain -p actions $KEY_CHAIN
# Make the keychain the default so identities are found
security default-keychain -s $KEY_CHAIN
# Unlock the keychain
security unlock-keychain -p actions $KEY_CHAIN
security import $CERTIFICATE_P12 -k $KEY_CHAIN -P $APPLE_CERTIFICATE_PASSWORD -T /usr/bin/codesign;
security set-key-partition-list -S apple-tool:,apple: -s -k actions $KEY_CHAIN
# remove certs
rm -fr *.p12

View File

@ -236,7 +236,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -254,7 +254,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -445,7 +445,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -463,7 +463,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -240,7 +240,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -258,7 +258,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -449,7 +449,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -467,7 +467,7 @@ const extrusion = extrude(5, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -155,7 +155,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -173,7 +173,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -364,7 +364,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -382,7 +382,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -575,7 +575,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -593,7 +593,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -784,7 +784,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -802,7 +802,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -154,7 +154,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -172,7 +172,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -363,7 +363,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -381,7 +381,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -574,7 +574,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -592,7 +592,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -783,7 +783,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -801,7 +801,7 @@ const extrusion = extrude(10, sketch001)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -156,7 +156,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -174,7 +174,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -365,7 +365,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -383,7 +383,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -576,7 +576,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -594,7 +594,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -785,7 +785,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -803,7 +803,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -248,7 +248,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -266,7 +266,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -457,7 +457,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -475,7 +475,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -668,7 +668,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -686,7 +686,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -877,7 +877,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -895,7 +895,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -153,7 +153,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -171,7 +171,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -362,7 +362,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -380,7 +380,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -573,7 +573,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -591,7 +591,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -782,7 +782,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -800,7 +800,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -153,7 +153,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -171,7 +171,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -362,7 +362,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -380,7 +380,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -573,7 +573,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -591,7 +591,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -782,7 +782,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -800,7 +800,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -166,7 +166,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -184,7 +184,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -375,7 +375,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -393,7 +393,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -586,7 +586,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -604,7 +604,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -795,7 +795,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -813,7 +813,7 @@ const exampleSketch = startSketchOn('XZ')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -159,7 +159,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -177,7 +177,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -368,7 +368,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -386,7 +386,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -579,7 +579,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -597,7 +597,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -788,7 +788,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -806,7 +806,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -381,7 +381,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -399,7 +399,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -785,7 +785,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -803,7 +803,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -152,7 +152,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -170,7 +170,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -528,7 +528,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -546,7 +546,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -739,7 +739,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -757,7 +757,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -948,7 +948,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -966,7 +966,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -154,7 +154,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -172,7 +172,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -363,7 +363,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -381,7 +381,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -574,7 +574,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -592,7 +592,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -783,7 +783,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -801,7 +801,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -179,7 +179,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -197,7 +197,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -389,7 +389,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -407,7 +407,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -719,7 +719,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -737,7 +737,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -411,7 +411,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -429,7 +429,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -815,7 +815,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -833,7 +833,7 @@ const mountingPlate = extrude(thickness, mountingPlateSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -35,7 +35,7 @@ const part001 = startSketchOn('XY')
// Start angle (in degrees).
angleStart: number,
// Is the helix rotation counter clockwise? The default is `false`.
ccw: string,
ccw: bool,
// Length of the helix. If this argument is not provided, the height of the extrude group is used.
length: number,
// Number of revolutions.
@ -282,7 +282,7 @@ const part001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -300,7 +300,7 @@ const part001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -677,7 +677,7 @@ const part001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -695,7 +695,7 @@ const part001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -165,7 +165,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -183,7 +183,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -375,7 +375,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -393,7 +393,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -577,7 +577,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -595,7 +595,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -786,7 +786,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -804,7 +804,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -988,7 +988,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -1006,7 +1006,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -1197,7 +1197,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -1215,7 +1215,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -145,7 +145,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -163,7 +163,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -354,7 +354,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -372,7 +372,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -145,7 +145,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -163,7 +163,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -354,7 +354,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -372,7 +372,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -158,7 +158,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -176,7 +176,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -367,7 +367,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -385,7 +385,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -578,7 +578,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -596,7 +596,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -787,7 +787,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -805,7 +805,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -145,7 +145,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -163,7 +163,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -354,7 +354,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -372,7 +372,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -565,7 +565,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -583,7 +583,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -774,7 +774,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -792,7 +792,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -45,7 +45,7 @@ const example = extrude(1, exampleSketch)
// The number of repetitions. Must be greater than 0. This excludes the original entity. For example, if `repetitions` is 1, the original entity will be copied once.
repetitions: number,
// Whether or not to rotate the duplicates as they are copied.
rotateDuplicates: string,
rotateDuplicates: bool,
}
```
* `sketch_group_set`: `SketchGroupSet` - A sketch group or a group of sketch groups. (REQUIRED)
@ -163,7 +163,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -181,7 +181,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -373,7 +373,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -391,7 +391,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -44,7 +44,7 @@ const example = extrude(-5, exampleSketch)
// The number of repetitions. Must be greater than 0. This excludes the original entity. For example, if `repetitions` is 1, the original entity will be copied once.
repetitions: number,
// Whether or not to rotate the duplicates as they are copied.
rotateDuplicates: string,
rotateDuplicates: bool,
}
```
* `extrude_group_set`: `ExtrudeGroupSet` - A extrude group or a group of extrude groups. (REQUIRED)
@ -287,7 +287,7 @@ const example = extrude(-5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -305,7 +305,7 @@ const example = extrude(-5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -156,7 +156,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -174,7 +174,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -366,7 +366,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -384,7 +384,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -285,7 +285,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -303,7 +303,7 @@ const example = extrude(1, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -287,7 +287,7 @@ let vase = layer()
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -305,7 +305,7 @@ let vase = layer()
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -146,7 +146,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -164,7 +164,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -355,7 +355,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -373,7 +373,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -141,7 +141,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -159,7 +159,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -350,7 +350,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -368,7 +368,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -140,7 +140,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -158,7 +158,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -349,7 +349,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -367,7 +367,7 @@ const sketch001 = startSketchOn('XY')
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -384,7 +384,7 @@ uuid |
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -402,7 +402,7 @@ uuid |
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -593,7 +593,7 @@ uuid |
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -611,7 +611,7 @@ uuid |
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -920,7 +920,7 @@ uuid |
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -938,7 +938,7 @@ uuid |
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -399,7 +399,7 @@ shell({ faces: [myTag], thickness: 0.25 }, firstSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -417,7 +417,7 @@ shell({ faces: [myTag], thickness: 0.25 }, firstSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -794,7 +794,7 @@ shell({ faces: [myTag], thickness: 0.25 }, firstSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -812,7 +812,7 @@ shell({ faces: [myTag], thickness: 0.25 }, firstSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -224,7 +224,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -242,7 +242,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -527,7 +527,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -545,7 +545,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -736,7 +736,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -754,7 +754,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -171,7 +171,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -189,7 +189,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -380,7 +380,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -398,7 +398,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -293,7 +293,7 @@ const a1 = startSketchOn({
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -311,7 +311,7 @@ const a1 = startSketchOn({
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -709,7 +709,7 @@ const a1 = startSketchOn({
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -727,7 +727,7 @@ const a1 = startSketchOn({
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -155,7 +155,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -173,7 +173,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -364,7 +364,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -382,7 +382,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -575,7 +575,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -593,7 +593,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -784,7 +784,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -802,7 +802,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -145,7 +145,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -163,7 +163,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -354,7 +354,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -372,7 +372,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -565,7 +565,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -583,7 +583,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -774,7 +774,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -792,7 +792,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -148,7 +148,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -166,7 +166,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -357,7 +357,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -375,7 +375,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -568,7 +568,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -586,7 +586,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -777,7 +777,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -795,7 +795,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -148,7 +148,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -166,7 +166,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -357,7 +357,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -375,7 +375,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -568,7 +568,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -586,7 +586,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -777,7 +777,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -795,7 +795,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -146,7 +146,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -164,7 +164,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -355,7 +355,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -373,7 +373,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -566,7 +566,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -584,7 +584,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -775,7 +775,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -793,7 +793,7 @@ const example = extrude(10, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -144,7 +144,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -162,7 +162,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -353,7 +353,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -371,7 +371,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -564,7 +564,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -582,7 +582,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -773,7 +773,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.
@ -791,7 +791,7 @@ const example = extrude(5, exampleSketch)
} |
{
// arc's direction
ccw: string,
ccw: bool,
// the arc's center
center: [number, number],
// The from point.

View File

@ -84,6 +84,7 @@ async function doBasicSketch(page: Page, openPanes: string[]) {
} else {
await page.waitForTimeout(500)
}
await page.waitForTimeout(200)
await page.mouse.click(startXPx, 500 - PUR * 20)
if (openPanes.includes('code')) {
await expect(u.codeLocator)
@ -95,15 +96,16 @@ async function doBasicSketch(page: Page, openPanes: string[]) {
}
// deselect line tool
await page.getByRole('button', { name: 'Line', exact: true }).click()
await page.waitForTimeout(500)
await page.getByTestId('line').click()
const line1 = await u.getSegmentBodyCoords(`[data-overlay-index="${0}"]`, 0)
if (openPanes.includes('code')) {
expect(await u.getGreatestPixDiff(line1, TEST_COLORS.WHITE)).toBeLessThan(3)
await expect(
await u.getGreatestPixDiff(line1, [249, 249, 249])
).toBeLessThan(3)
await expect
.poll(async () => u.getGreatestPixDiff(line1, TEST_COLORS.WHITE))
.toBeLessThan(3)
await expect
.poll(() => u.getGreatestPixDiff(line1, [249, 249, 249]))
.toBeLessThan(3)
}
// click between first two clicks to get center of the line
await page.mouse.click(startXPx + PUR * 15, 500 - PUR * 10)
@ -137,6 +139,8 @@ async function doBasicSketch(page: Page, openPanes: string[]) {
test.describe('Basic sketch', () => {
test('code pane open at start', async ({ page }) => {
// Skip on windows it is being weird.
test.skip(process.platform === 'win32', 'Skip on windows')
await doBasicSketch(page, ['code'])
})

View File

@ -61,7 +61,7 @@ test.describe('Can create sketches on all planes and their back sides', () => {
await page.waitForTimeout(300) // wait for animation
await expect(
page.getByRole('button', { name: 'Line', exact: true })
page.getByRole('button', { name: 'line Line', exact: true })
).toBeVisible()
// draw a line
@ -72,7 +72,10 @@ test.describe('Can create sketches on all planes and their back sides', () => {
await expect(page.locator('.cm-content')).toHaveText(code)
await page.getByRole('button', { name: 'Line', exact: true }).click()
await page
.getByRole('button', { name: 'line Line', exact: true })
.first()
.click()
await u.openAndClearDebugPanel()
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await u.expectCmdLog('[data-message-type="execution-done"]')

View File

@ -12,47 +12,50 @@ test.afterEach(async ({ page }, testInfo) => {
})
test.describe('Command bar tests', () => {
test('Extrude from command bar selects extrude line after', async ({
page,
}) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`const sketch001 = startSketchOn('XY')
// TODO fixme: enter is not working in the command bar
test.fixme(
'Extrude from command bar selects extrude line after',
async ({ page }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
`const sketch001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> xLine(-20, %)
|> close(%)
`
)
})
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
// Click the line of code for xLine.
await page.getByText(`close(%)`).click() // TODO remove this and reinstate // await topHorzSegmentClick()
await page.waitForTimeout(100)
await page.getByRole('button', { name: 'Extrude' }).click()
await page.waitForTimeout(200)
await page.keyboard.press('Enter')
await page.waitForTimeout(200)
await page.keyboard.press('Enter')
await page.waitForTimeout(200)
await expect(page.locator('.cm-activeLine')).toHaveText(
`const extrude001 = extrude(${KCL_DEFAULT_LENGTH}, sketch001)`
)
})
}
)
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart()
await u.openDebugPanel()
await u.expectCmdLog('[data-message-type="execution-done"]')
await u.closeDebugPanel()
// Click the line of code for xLine.
await page.getByText(`close(%)`).click() // TODO remove this and reinstate // await topHorzSegmentClick()
await page.waitForTimeout(100)
await page.getByRole('button', { name: 'Extrude' }).click()
await page.waitForTimeout(100)
await page.keyboard.press('Enter')
await page.waitForTimeout(100)
await page.keyboard.press('Enter')
await page.waitForTimeout(100)
await expect(page.locator('.cm-activeLine')).toHaveText(
`const extrude001 = extrude(${KCL_DEFAULT_LENGTH}, sketch001)`
)
})
test('Fillet from command bar', async ({ page }) => {
// TODO fixme: enter is not working in the command bar
test.fixme('Fillet from command bar', async ({ page }) => {
await page.addInitScript(async () => {
localStorage.setItem(
'persistCode',
@ -321,20 +324,18 @@ const extrude001 = extrude(distance001, sketch001)`.replace(
name: 'rectangle',
})
const rectangleToolButton = page.getByRole('button', {
name: 'Corner rectangle',
exact: true,
name: 'rectangle Corner rectangle',
})
const lineToolCommand = page.getByRole('option', {
name: 'Line',
})
const lineToolButton = page.getByRole('button', {
name: 'Line',
name: 'line Line',
exact: true,
})
const arcToolCommand = page.getByRole('option', { name: 'Tangential Arc' })
const arcToolButton = page.getByRole('button', {
name: 'Tangential Arc',
exact: true,
name: 'arc Tangential Arc',
})
// Start a sketch

View File

@ -682,10 +682,6 @@ test.describe('Editor tests', () => {
})
await page.waitForTimeout(100)
const startPX = [665, 458]
const dragPX = 40
await page.getByText('startProfileAt([4.61, -14.01], %)').click()
await expect(page.getByRole('button', { name: 'Extrude' })).toBeVisible()
await page.getByRole('button', { name: 'Extrude' }).click()
@ -693,10 +689,10 @@ test.describe('Editor tests', () => {
await expect(page.getByTestId('command-bar')).toBeVisible()
await page.waitForTimeout(100)
await page.keyboard.press('Enter')
await page.getByRole('button', { name: 'arrow right Continue' }).click()
await page.waitForTimeout(100)
await expect(page.getByText('Confirm Extrude')).toBeVisible()
await page.keyboard.press('Enter')
await page.getByRole('button', { name: 'checkmark Submit command' }).click()
await page.waitForTimeout(100)
// expect the code to have changed

View File

@ -1,6 +1,6 @@
import { test, expect } from '@playwright/test'
import { getUtils, setup, tearDown } from './test-utils'
import fsp from 'fs/promises'
import { getUtils, setup, setupElectron, tearDown } from './test-utils'
import { bracket } from 'lib/exampleKcl'
import { onboardingPaths } from 'routes/Onboarding/paths'
import {
@ -12,7 +12,10 @@ import {
} from './storageStates'
import * as TOML from '@iarna/toml'
test.beforeEach(async ({ context, page }) => {
test.beforeEach(async ({ context, page }, testInfo) => {
if (testInfo.tags.includes('@electron')) {
return
}
await setup(context, page)
})
@ -339,3 +342,96 @@ test.describe('Onboarding tests', () => {
}
})
})
test(
'Restarting onboarding on desktop takes one attempt',
{ tag: '@electron' },
async ({ browser: _ }, testInfo) => {
const { electronApp, page } = await setupElectron({
testInfo,
folderSetupFn: async (dir) => {
await fsp.mkdir(`${dir}/router-template-slate`, { recursive: true })
await fsp.copyFile(
'src/wasm-lib/tests/executor/inputs/router-template-slate.kcl',
`${dir}/router-template-slate/main.kcl`
)
},
})
// Our constants
const u = await getUtils(page)
const projectCard = page.getByText('router-template-slate')
const helpMenuButton = page.getByRole('button', {
name: 'Help and resources',
})
const restartOnboardingButton = page.getByRole('button', {
name: 'Reset onboarding',
})
const restartConfirmationButton = page.getByRole('button', {
name: 'Make a new project',
})
const tutorialProjectIndicator = page.getByText('Tutorial Project 00')
const tutorialModalText = page.getByText('Welcome to Modeling App!')
const tutorialDismissButton = page.getByRole('button', { name: 'Dismiss' })
const userMenuButton = page.getByTestId('user-sidebar-toggle')
const userMenuSettingsButton = page.getByRole('button', {
name: 'User settings',
})
const settingsHeading = page.getByRole('heading', {
name: 'Settings',
exact: true,
})
const restartOnboardingSettingsButton = page.getByRole('button', {
name: 'Replay onboarding',
})
await test.step('Navigate into project', async () => {
await page.setViewportSize({ width: 1200, height: 500 })
page.on('console', console.log)
await expect(
page.getByRole('heading', { name: 'Your Projects' })
).toBeVisible()
await expect(projectCard).toBeVisible()
await projectCard.click()
await u.waitForPageLoad()
})
await test.step('Restart the onboarding from help menu', async () => {
await helpMenuButton.click()
await restartOnboardingButton.click()
await expect(restartConfirmationButton).toBeVisible()
await restartConfirmationButton.click()
})
await test.step('Confirm that the onboarding has restarted', async () => {
await expect(tutorialProjectIndicator).toBeVisible()
await expect(tutorialModalText).toBeVisible()
await tutorialDismissButton.click()
})
await test.step('Clear code and restart onboarding from settings', async () => {
await u.openKclCodePanel()
await expect(u.codeLocator).toContainText('// Shelf Bracket')
await u.codeLocator.selectText()
await u.codeLocator.fill('')
await test.step('Navigate to settings', async () => {
await userMenuButton.click()
await userMenuSettingsButton.click()
await expect(settingsHeading).toBeVisible()
await expect(restartOnboardingSettingsButton).toBeVisible()
})
await restartOnboardingSettingsButton.click()
// Since the code is empty, we should not see the confirmation dialog
await expect(restartConfirmationButton).not.toBeVisible()
await expect(tutorialProjectIndicator).toBeVisible()
await expect(tutorialModalText).toBeVisible()
})
await electronApp.close()
}
)

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,8 @@
import { test, expect, Page } from '@playwright/test'
import { getUtils, setup, tearDown } from './test-utils'
import * as fsp from 'fs/promises'
import { getUtils, setup, setupElectron, tearDown } from './test-utils'
import { TEST_CODE_TRIGGER_ENGINE_EXPORT_ERROR } from './storageStates'
import { bracket } from 'lib/exampleKcl'
import {
PLAYWRIGHT_MOCK_EXPORT_DURATION,
PLAYWRIGHT_TOAST_DURATION,
} from 'lib/constants'
test.beforeEach(async ({ context, page }) => {
await setup(context, page)
@ -158,6 +154,12 @@ const sketch001 = startSketchAt([-0, -0])
await expect(zooLogo).not.toHaveAttribute('href')
})
test('Position _ Is Out Of Range... regression test', async ({ page }) => {
// SKip on windows, its being weird.
test.skip(
process.platform === 'win32',
'This test is being weird on windows'
)
const u = await getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 })
@ -229,6 +231,7 @@ const sketch001 = startSketchAt([-0, -0])
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
})
test('when engine fails export we handle the failure and alert the user', async ({
page,
}) => {
@ -332,22 +335,20 @@ const sketch001 = startSketchAt([-0, -0])
test('ensure you can not export while an export is already going', async ({
page,
}) => {
// This is being weird on ubuntu and windows.
test.skip(
process.platform === 'linux' || process.platform === 'win32',
'This test is being weird on ubuntu'
)
const u = await getUtils(page)
await test.step('Set up the code and durations', async () => {
await page.addInitScript(
async ({ code, toastDurationKey, exportDurationKey }) => {
async ({ code }) => {
localStorage.setItem('persistCode', code)
// Normally we make these durations short to speed up PW tests
// to superhuman speeds. But in this case we want to make sure
// the export toast is visible for a while, and the export
// duration is long enough to make sure the export toast is visible
localStorage.setItem(toastDurationKey, '1500')
localStorage.setItem(exportDurationKey, '750')
},
{
code: bracket,
toastDurationKey: PLAYWRIGHT_TOAST_DURATION,
exportDurationKey: PLAYWRIGHT_MOCK_EXPORT_DURATION,
}
)
@ -414,6 +415,52 @@ const sketch001 = startSketchAt([-0, -0])
await expect(successToastMessage).toBeVisible()
})
})
test(
`Network health indicator only appears in modeling view`,
{ tag: '@electron' },
async ({ browserName: _ }, testInfo) => {
const { electronApp, page } = await setupElectron({
testInfo,
folderSetupFn: async (dir) => {
await fsp.mkdir(`${dir}/bracket`, { recursive: true })
await fsp.copyFile(
'src/wasm-lib/tests/executor/inputs/focusrite_scarlett_mounting_braket.kcl',
`${dir}/bracket/main.kcl`
)
},
})
await page.setViewportSize({ width: 1200, height: 500 })
const u = await getUtils(page)
// Locators
const projectsHeading = page.getByRole('heading', {
name: 'Your projects',
})
const projectLink = page.getByRole('link', { name: 'bracket' })
const networkHealthIndicator = page.getByTestId('network-toggle')
await test.step('Check the home page', async () => {
await expect(projectsHeading).toBeVisible()
await expect(projectLink).toBeVisible()
await expect(networkHealthIndicator).not.toBeVisible()
})
await test.step('Open the project', async () => {
await projectLink.click()
})
await test.step('Check the modeling view', async () => {
await expect(networkHealthIndicator).toBeVisible()
await expect(networkHealthIndicator).toContainText('Problem')
await u.waitForPageLoad()
await expect(networkHealthIndicator).toContainText('Connected')
})
await electronApp.close()
}
)
})
async function clickExportButton(page: Page) {

View File

@ -146,7 +146,7 @@ test.describe('Sketch tests', () => {
await u.expectCmdLog('[data-message-type="execution-done"]', 10_000)
await page.waitForTimeout(100)
await page.getByRole('button', { name: 'Line', exact: true }).click()
await page.getByRole('button', { name: 'line Line', exact: true }).click()
await page.waitForTimeout(100)
await page.mouse.click(700, 200)
@ -725,7 +725,7 @@ test.describe('Sketch tests', () => {
await expect(page.locator('.cm-content')).toHaveText(code)
// Assert the tool was unequipped
await expect(
page.getByRole('button', { name: 'Line', exact: true })
page.getByRole('button', { name: 'line Line', exact: true })
).not.toHaveAttribute('aria-pressed', 'true')
// exit sketch

View File

@ -7,7 +7,11 @@ import { spawn } from 'child_process'
import { KCL_DEFAULT_LENGTH } from 'lib/constants'
import JSZip from 'jszip'
import path from 'path'
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from './storageStates'
import {
IS_PLAYWRIGHT_KEY,
TEST_SETTINGS,
TEST_SETTINGS_KEY,
} from './storageStates'
import * as TOML from '@iarna/toml'
test.beforeEach(async ({ page }) => {
@ -16,16 +20,17 @@ test.beforeEach(async ({ page }) => {
// set the default settings
await page.addInitScript(
async ({ token, settingsKey, settings }) => {
async ({ token, settingsKey, settings, IS_PLAYWRIGHT_KEY }) => {
localStorage.setItem('TOKEN_PERSIST_KEY', token)
localStorage.setItem('persistCode', ``)
localStorage.setItem(settingsKey, settings)
localStorage.setItem('playwright', 'true')
localStorage.setItem(IS_PLAYWRIGHT_KEY, 'true')
},
{
token: secrets.token,
settingsKey: TEST_SETTINGS_KEY,
settings: TOML.stringify({ settings: TEST_SETTINGS }),
IS_PLAYWRIGHT_KEY: IS_PLAYWRIGHT_KEY,
}
)
@ -46,6 +51,12 @@ test(
'exports of each format should work',
{ tag: '@snapshot' },
async ({ page, context }) => {
// skip on macos and windows.
test.skip(
process.platform === 'darwin' || process.platform === 'win32',
'Skip on macos and windows'
)
// FYI this test doesn't work with only engine running locally
// And you will need to have the KittyCAD CLI installed
const u = await getUtils(page)
@ -365,6 +376,9 @@ test.describe(
'extrude on default planes should be stable',
{ tag: '@snapshot' },
() => {
// FIXME: Skip on macos its being weird.
test.skip(process.platform === 'darwin', 'Skip on macos')
test('XY', async ({ page, context }) => {
await extrudeDefaultPlane(context, page, 'XY')
})
@ -395,6 +409,9 @@ test(
'Draft segments should look right',
{ tag: '@snapshot' },
async ({ page, context }) => {
// FIXME: Skip on macos its being weird.
test.skip(process.platform === 'darwin', 'Skip on macos')
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
@ -445,7 +462,7 @@ test(
await expect(page.locator('.cm-content')).toHaveText(code)
await page
.getByRole('button', { name: 'Tangential Arc', exact: true })
.getByRole('button', { name: 'arc Tangential Arc', exact: true })
.click()
await page.mouse.move(startXPx + PUR * 30, 500 - PUR * 20, { steps: 10 })
@ -462,6 +479,9 @@ test(
'Draft rectangles should look right',
{ tag: '@snapshot' },
async ({ page, context }) => {
// FIXME: Skip on macos its being weird.
test.skip(process.platform === 'darwin', 'Skip on macos')
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
const PUR = 400 / 37.5 //pixeltoUnitRatio
@ -496,9 +516,9 @@ test(
const startXPx = 600
// Equip the rectangle tool
await page.getByRole('button', { name: 'Line', exact: true }).click()
await page.getByRole('button', { name: 'line Line', exact: true }).click()
await page
.getByRole('button', { name: 'Corner rectangle', exact: true })
.getByRole('button', { name: 'rectangle Corner rectangle', exact: true })
.click()
// Draw the rectangle
@ -516,6 +536,9 @@ test.describe(
'Client side scene scale should match engine scale',
{ tag: '@snapshot' },
() => {
// FIXME: Skip on macos its being weird.
test.skip(process.platform === 'darwin', 'Skip on macos')
test('Inch scale', async ({ page }) => {
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
@ -563,7 +586,7 @@ test.describe(
await expect(u.codeLocator).toHaveText(code)
await page
.getByRole('button', { name: 'Tangential Arc', exact: true })
.getByRole('button', { name: 'arc Tangential Arc', exact: true })
.click()
await page.waitForTimeout(100)
@ -575,7 +598,7 @@ test.describe(
// click tangential arc tool again to unequip it
await page
.getByRole('button', { name: 'Tangential Arc', exact: true })
.getByRole('button', { name: 'arc Tangential Arc', exact: true })
.click()
await page.waitForTimeout(100)
@ -666,7 +689,7 @@ test.describe(
await expect(u.codeLocator).toHaveText(code)
await page
.getByRole('button', { name: 'Tangential Arc', exact: true })
.getByRole('button', { name: 'arc Tangential Arc', exact: true })
.click()
await page.waitForTimeout(100)
@ -677,7 +700,7 @@ test.describe(
await expect(u.codeLocator).toHaveText(code)
await page
.getByRole('button', { name: 'Tangential Arc', exact: true })
.getByRole('button', { name: 'arc Tangential Arc', exact: true })
.click()
await page.waitForTimeout(100)
@ -710,6 +733,9 @@ test(
'Sketch on face with none z-up',
{ tag: '@snapshot' },
async ({ page, context }) => {
// FIXME: Skip on macos its being weird.
test.skip(process.platform === 'darwin', 'Skip on macos')
const u = await getUtils(page)
await context.addInitScript(async (KCL_DEFAULT_LENGTH) => {
localStorage.setItem(
@ -772,6 +798,9 @@ test(
'Zoom to fit on load - solid 2d',
{ tag: '@snapshot' },
async ({ page, context }) => {
// FIXME: Skip on macos its being weird.
test.skip(process.platform === 'darwin', 'Skip on macos')
const u = await getUtils(page)
await context.addInitScript(async () => {
localStorage.setItem(
@ -812,6 +841,9 @@ test(
'Zoom to fit on load - solid 3d',
{ tag: '@snapshot' },
async ({ page, context }) => {
// FIXME: Skip on macos its being weird.
test.skip(process.platform === 'darwin', 'Skip on macos')
const u = await getUtils(page)
await context.addInitScript(async () => {
localStorage.setItem(
@ -850,6 +882,9 @@ test(
)
test.describe('Grid visibility', { tag: '@snapshot' }, () => {
// FIXME: Skip on macos its being weird.
test.skip(process.platform === 'darwin', 'Skip on macos')
test('Grid turned off', async ({ page }) => {
const u = await getUtils(page)
const stream = page.getByTestId('stream')

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -2,6 +2,8 @@ import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
import { Themes } from 'lib/theme'
import { onboardingPaths } from 'routes/Onboarding/paths'
export const IS_PLAYWRIGHT_KEY = 'playwright'
export const TEST_SETTINGS_KEY = '/settings.toml'
export const TEST_SETTINGS = {
app: {

View File

@ -198,7 +198,7 @@ test.describe('Test network and connection issues', () => {
await page.waitForTimeout(150)
// Click the line tool
await page.getByRole('button', { name: 'Line', exact: true }).click()
await page.getByRole('button', { name: 'line Line', exact: true }).click()
await page.waitForTimeout(150)
@ -230,7 +230,7 @@ test.describe('Test network and connection issues', () => {
page.getByRole('button', { name: 'Exit Sketch' })
).toBeVisible()
await expect(
page.getByRole('button', { name: 'Line', exact: true })
page.getByRole('button', { name: 'line Line', exact: true })
).not.toHaveAttribute('aria-pressed', 'true')
// Exit sketch

View File

@ -4,19 +4,27 @@ import {
Download,
TestInfo,
BrowserContext,
_electron as electron,
} from '@playwright/test'
import { EngineCommand } from 'lang/std/artifactGraph'
import os from 'os'
import fsp from 'fs/promises'
import fsSync from 'fs'
import { join } from 'path'
import pixelMatch from 'pixelmatch'
import { PNG } from 'pngjs'
import { Protocol } from 'playwright-core/types/protocol'
import type { Models } from '@kittycad/lib'
import { APP_NAME, COOKIE_NAME } from 'lib/constants'
import waitOn from 'wait-on'
import { secrets } from './secrets'
import { TEST_SETTINGS_KEY, TEST_SETTINGS } from './storageStates'
import {
TEST_SETTINGS_KEY,
TEST_SETTINGS,
IS_PLAYWRIGHT_KEY,
} from './storageStates'
import * as TOML from '@iarna/toml'
import { SaveSettingsPayload } from 'lib/settings/settingsTypes'
import { SETTINGS_FILE_NAME } from 'lib/constants'
type TestColor = [number, number, number]
export const TEST_COLORS = {
@ -44,7 +52,7 @@ async function waitForPageLoadWithRetry(page: Page) {
})
await expect(
page.getByRole('button', { name: 'Start Sketch' }),
page.getByRole('button', { name: 'sketch Start Sketch' }),
errorMessage
).toBeEnabled({
timeout: 20_000,
@ -322,7 +330,7 @@ export async function getUtils(page: Page) {
getSegmentBodyCoords: async (locator: string, px = 30) => {
const overlay = page.locator(locator)
const bbox = await overlay
.boundingBox({ timeout: 5000 })
.boundingBox({ timeout: 5_000 })
.then((box) => ({ ...box, x: box?.x || 0, y: box?.y || 0 }))
const angle = Number(await overlay.getAttribute('data-overlay-angle'))
const angleXOffset = Math.cos(((angle - 180) * Math.PI) / 180) * px
@ -339,7 +347,7 @@ export async function getUtils(page: Page) {
getBoundingBox: async (locator: string) =>
page
.locator(locator)
.boundingBox()
.boundingBox({ timeout: 5_000 })
.then((box) => ({ ...box, x: box?.x || 0, y: box?.y || 0 })),
codeLocator: page.locator('.cm-content'),
normalisedEditorCode: async () => {
@ -530,14 +538,19 @@ export interface Paths {
export const doExport = async (
output: Models['OutputFormat_type'],
page: Page
page: Page,
isElectron = false
): Promise<Paths> => {
await page.getByRole('button', { name: APP_NAME }).click()
const exportMenuButton = page.getByRole('button', {
name: 'Export current part',
})
await expect(exportMenuButton).toBeVisible()
await exportMenuButton.click()
if (!isElectron) {
await page.getByRole('button', { name: APP_NAME }).click()
const exportMenuButton = page.getByRole('button', {
name: 'Export current part',
})
await expect(exportMenuButton).toBeVisible()
await exportMenuButton.click()
} else {
await page.getByTestId('export-pane-button').click()
}
await expect(page.getByTestId('command-bar')).toBeVisible()
// Go through export via command bar
@ -564,13 +577,21 @@ export const doExport = async (
const [downloadPromise1, downloadResolve1] = getPromiseAndResolve()
let downloadCnt = 0
page.on('download', async (download) => {
if (downloadCnt === 0) {
downloadResolve1(download)
}
downloadCnt++
})
if (!isElectron)
page.on('download', async (download) => {
if (downloadCnt === 0) {
downloadResolve1(download)
}
downloadCnt++
})
await page.getByRole('button', { name: 'Submit command' }).click()
if (isElectron) {
return {
modelPath: '',
imagePath: '',
outputType: output.type,
}
}
// Handle download
const download = await downloadPromise1
@ -623,24 +644,32 @@ export async function tearDown(page: Page, testInfo: TestInfo) {
await page.waitForTimeout(3000)
}
// settingsOverrides may need to be augmented to take more generic items,
// but we'll be strict for now
export async function setup(context: BrowserContext, page: Page) {
// wait for Vite preview server to be up
await waitOn({
resources: ['tcp:3000'],
timeout: 5000,
})
await context.addInitScript(
async ({ token, settingsKey, settings }) => {
async ({ token, settingsKey, settings, IS_PLAYWRIGHT_KEY }) => {
localStorage.setItem('TOKEN_PERSIST_KEY', token)
localStorage.setItem('persistCode', ``)
localStorage.setItem(settingsKey, settings)
localStorage.setItem('playwright', 'true')
localStorage.setItem(IS_PLAYWRIGHT_KEY, 'true')
console.log('TEST_SETTINGS.projects', settings)
},
{
token: secrets.token,
settingsKey: TEST_SETTINGS_KEY,
settings: TOML.stringify({ settings: TEST_SETTINGS }),
settings: TOML.stringify({
settings: {
...TEST_SETTINGS,
app: {
...TEST_SETTINGS.projects,
projectDirectory: TEST_SETTINGS.app.projectDirectory,
onboardingStatus: 'dismissed',
theme: 'dark',
},
} as Partial<SaveSettingsPayload>,
}),
IS_PLAYWRIGHT_KEY,
}
)
@ -656,3 +685,63 @@ export async function setup(context: BrowserContext, page: Page) {
// kill animations, speeds up tests and reduced flakiness
await page.emulateMedia({ reducedMotion: 'reduce' })
}
export async function setupElectron({
testInfo,
folderSetupFn,
cleanProjectDir = true,
}: {
testInfo: TestInfo
folderSetupFn?: (projectDirName: string) => Promise<void>
cleanProjectDir?: boolean
}) {
// create or otherwise clear the folder
const projectDirName = testInfo.outputPath('electron-test-projects-dir')
try {
if (fsSync.existsSync(projectDirName) && cleanProjectDir) {
await fsp.rm(projectDirName, { recursive: true })
}
} catch (e) {
console.error(e)
}
if (cleanProjectDir) {
await fsp.mkdir(projectDirName)
}
const electronApp = await electron.launch({
args: ['.', '--no-sandbox'],
env: {
...process.env,
TEST_SETTINGS_FILE_KEY: projectDirName,
IS_PLAYWRIGHT: 'true',
},
...(process.env.ELECTRON_OVERRIDE_DIST_PATH
? { executablePath: process.env.ELECTRON_OVERRIDE_DIST_PATH + 'electron' }
: {}),
})
const context = electronApp.context()
const page = await electronApp.firstWindow()
context.on('console', console.log)
page.on('console', console.log)
if (cleanProjectDir) {
const tempSettingsFilePath = join(projectDirName, SETTINGS_FILE_NAME)
const settingsOverrides = TOML.stringify({
...TEST_SETTINGS,
settings: {
app: {
...TEST_SETTINGS.app,
projectDirectory: projectDirName,
},
},
})
await fsp.writeFile(tempSettingsFilePath, settingsOverrides)
}
await folderSetupFn?.(projectDirName)
await setup(context, page)
return { electronApp, page }
}

View File

@ -174,166 +174,168 @@ test.describe('Testing Camera Movement', () => {
}, [0, -85, -85])
})
test('Zoom should be consistent when exiting or entering sketches', async ({
page,
}) => {
// start new sketch pan and zoom before exiting, when exiting the sketch should stay in the same place
// than zoom and pan outside of sketch mode and enter again and it should not change from where it is
// than again for sketching
// TODO fixme something is wrong with sketch here
test.fixme(
'Zoom should be consistent when exiting or entering sketches',
async ({ page }) => {
// start new sketch pan and zoom before exiting, when exiting the sketch should stay in the same place
// than zoom and pan outside of sketch mode and enter again and it should not change from where it is
// than again for sketching
test.skip(process.platform !== 'darwin', 'Zoom should be consistent')
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
test.skip(process.platform !== 'darwin', 'Zoom should be consistent')
const u = await getUtils(page)
await page.setViewportSize({ width: 1200, height: 500 })
await u.waitForAuthSkipAppStart()
await u.openDebugPanel()
await u.waitForAuthSkipAppStart()
await u.openDebugPanel()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).not.toBeDisabled()
await expect(
page.getByRole('button', { name: 'Start Sketch' })
).toBeVisible()
// click on "Start Sketch" button
await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(100)
// select a plane
await page.mouse.click(700, 325)
let code = `const sketch001 = startSketchOn('XY')`
await expect(u.codeLocator).toHaveText(code)
await u.closeDebugPanel()
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
// move the camera slightly
await page.keyboard.down('Shift')
await page.mouse.move(700, 300)
await page.mouse.down({ button: 'right' })
await page.mouse.move(800, 200)
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Shift')
let y = 350,
x = 948
await u.canvasLocator.click({ position: { x: 783, y } })
code += `\n |> startProfileAt([8.12, -12.98], %)`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y } })
code += `\n |> line([11.18, 0], %)`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y: 275 } })
code += `\n |> line([0, 6.99], %)`
// await expect(u.codeLocator).toHaveText(code)
// click the line button
await page.getByRole('button', { name: 'Line', exact: true }).click()
const hoverOverNothing = async () => {
// await u.canvasLocator.hover({position: {x: 700, y: 325}})
await page.mouse.move(700, 325)
// click on "Start Sketch" button
await u.clearCommandLogs()
await page.getByRole('button', { name: 'Start Sketch' }).click()
await page.waitForTimeout(100)
await expect(page.getByTestId('hover-highlight')).not.toBeVisible({
// select a plane
await page.mouse.click(700, 325)
let code = `const sketch001 = startSketchOn('XY')`
await expect(u.codeLocator).toHaveText(code)
await u.closeDebugPanel()
await page.waitForTimeout(500) // TODO detect animation ending, or disable animation
// move the camera slightly
await page.keyboard.down('Shift')
await page.mouse.move(700, 300)
await page.mouse.down({ button: 'right' })
await page.mouse.move(800, 200)
await page.mouse.up({ button: 'right' })
await page.keyboard.up('Shift')
let y = 350,
x = 948
await u.canvasLocator.click({ position: { x: 783, y } })
code += `\n |> startProfileAt([8.12, -12.98], %)`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y } })
code += `\n |> line([11.18, 0], %)`
// await expect(u.codeLocator).toHaveText(code)
await u.canvasLocator.click({ position: { x, y: 275 } })
code += `\n |> line([0, 6.99], %)`
// await expect(u.codeLocator).toHaveText(code)
// click the line button
await page.getByRole('button', { name: 'line Line', exact: true }).click()
const hoverOverNothing = async () => {
// await u.canvasLocator.hover({position: {x: 700, y: 325}})
await page.mouse.move(700, 325)
await page.waitForTimeout(100)
await expect(page.getByTestId('hover-highlight')).not.toBeVisible({
timeout: 10_000,
})
}
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
await page.waitForTimeout(200)
// hover over horizontal line
await u.canvasLocator.hover({ position: { x: 800, y } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over vertical line
await u.canvasLocator.hover({ position: { x, y: 325 } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// click exit sketch
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(400)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over horizontal line
await page.mouse.move(858, y, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(x, 325)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(857, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
// now click it
await page.mouse.click(857, y)
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeVisible()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
await page.waitForTimeout(400)
await hoverOverNothing()
x = 975
y = 468
await page.waitForTimeout(100)
await page.mouse.move(x, 419, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
await page.mouse.move(x, 419)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
}
await expect(page.getByTestId('hover-highlight')).not.toBeVisible()
await page.waitForTimeout(200)
// hover over horizontal line
await u.canvasLocator.hover({ position: { x: 800, y } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over vertical line
await u.canvasLocator.hover({ position: { x, y: 325 } })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// click exit sketch
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(400)
await hoverOverNothing()
await page.waitForTimeout(200)
// hover over horizontal line
await page.mouse.move(858, y, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(x, 325)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
// hover over vertical line
await page.mouse.move(857, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
// now click it
await page.mouse.click(857, y)
await expect(
page.getByRole('button', { name: 'Edit Sketch' })
).toBeVisible()
await page.getByRole('button', { name: 'Edit Sketch' }).click()
await page.waitForTimeout(400)
await hoverOverNothing()
x = 975
y = 468
await page.waitForTimeout(100)
await page.mouse.move(x, 419, { steps: 5 })
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.getByRole('button', { name: 'Exit Sketch' }).click()
await page.waitForTimeout(200)
await hoverOverNothing()
await page.waitForTimeout(200)
await page.mouse.move(x, 419)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
await hoverOverNothing()
await page.mouse.move(855, y)
await expect(page.getByTestId('hover-highlight').first()).toBeVisible({
timeout: 10_000,
})
})
)
})

Some files were not shown because too many files have changed in this diff Show More