Compare commits
125 Commits
max/bug-de
...
codex/fix-
Author | SHA1 | Date | |
---|---|---|---|
9b901dfe51 | |||
416de9a9fb | |||
da65426ddc | |||
585b485852 | |||
e85f16ff9c | |||
e7d2289a14 | |||
d35531758d | |||
729e0a7949 | |||
620b7401aa | |||
e3e67b00d5 | |||
49d4f8e5c3 | |||
47b159c605 | |||
c7b086fa69 | |||
203db79204 | |||
48a4fd8373 | |||
17eb84325f | |||
ebf048478d | |||
28a8cd2421 | |||
1506de92f5 | |||
8a03413643 | |||
f59b806a88 | |||
23a0085c78 | |||
a280a8c3f0 | |||
11620dfa6b | |||
f6e26e0bab | |||
f6b3a55cbf | |||
74939e5cd6 | |||
9906c9947a | |||
48d6a21f0a | |||
dd6a980915 | |||
2516df3a39 | |||
52125f0566 | |||
e489222b6a | |||
d93a57d7bf | |||
d34aea345b | |||
0b6102b0ac | |||
9e0873ed84 | |||
8587eb5fea | |||
b898c27e74 | |||
3026866a16 | |||
92fc294eae | |||
21e967ea7f | |||
3f00e7186c | |||
d3a4fd8b55 | |||
2be7107cca | |||
94f194a984 | |||
4fe880a970 | |||
8f5fbfc273 | |||
e660f52bb0 | |||
d74fdd9369 | |||
334145f0be | |||
c24073b6ae | |||
078b7f3bf7 | |||
3d65676ccb | |||
ce566fb6e5 | |||
b23fc9f623 | |||
5c2dfb8e40 | |||
0e341d7863 | |||
6a03ff9596 | |||
d7bd0c937d | |||
d3b2483f4f | |||
7838b7c9fd | |||
130ecf1f88 | |||
550d8b3753 | |||
696222a070 | |||
edb424988d | |||
1e487ef3bd | |||
811ef3e72d | |||
980e3c4bc2 | |||
78b6854c6b | |||
068b9129cf | |||
05fba3c50c | |||
7944a4ce41 | |||
4640f1a3ad | |||
cd79059d97 | |||
2d95e19048 | |||
d047587bc1 | |||
128e1093fb | |||
afdc305e3e | |||
4bc5439996 | |||
be14022f97 | |||
eda78ef5ae | |||
0cc833e687 | |||
33e83747f3 | |||
c3a8fc6d93 | |||
8ff84e269c | |||
99cb6a6179 | |||
13dbfdfaa4 | |||
8603f5c53a | |||
d5cc9e8386 | |||
533e17466b | |||
01c7b69f50 | |||
47feae3bd9 | |||
e7ecd655c4 | |||
d9e538c6ea | |||
e297f8286f | |||
b3bc90bbe4 | |||
95a02cbcd7 | |||
a049768f1c | |||
818d9a0d77 | |||
1a8f80a7dc | |||
566c9eaf10 | |||
e6485c2da1 | |||
0479edd36a | |||
87c1e92134 | |||
8f950ac1b0 | |||
78e4f43708 | |||
270436f404 | |||
57e61632a9 | |||
884191b8bb | |||
21b92f5f13 | |||
5599a75dbd | |||
3a06ae6e34 | |||
22857d77e9 | |||
1a325d0b29 | |||
1240b23080 | |||
8445080d7a | |||
bbe89f56a7 | |||
86e8bcfe0b | |||
21ccf129d6 | |||
dfc4b7d0c5 | |||
17b1120a27 | |||
2b509a515b | |||
97594b9a9e | |||
c65190a158 |
40
.github/ci-cd-scripts/upload-results.sh
vendored
@ -1,13 +1,41 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-}}"
|
if [ -z "${TAB_API_URL:-}" ] || [ -z "${TAB_API_KEY:-}" ]; then
|
||||||
COMMIT="${CI_COMMIT_SHA:-${GITHUB_SHA:-}}"
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
curl --request POST \
|
project="https://github.com/KittyCAD/modeling-app"
|
||||||
|
branch="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME:-}}"
|
||||||
|
commit="${CI_COMMIT_SHA:-${GITHUB_SHA:-}}"
|
||||||
|
|
||||||
|
echo "Uploading batch results"
|
||||||
|
curl --silent --request POST \
|
||||||
--header "X-API-Key: ${TAB_API_KEY}" \
|
--header "X-API-Key: ${TAB_API_KEY}" \
|
||||||
--form "project=https://github.com/KittyCAD/modeling-app" \
|
--form "project=${project}" \
|
||||||
--form "branch=${BRANCH}" \
|
--form "branch=${branch}" \
|
||||||
--form "commit=${COMMIT}" \
|
--form "commit=${commit}" \
|
||||||
--form "tests=@test-results/junit.xml" \
|
--form "tests=@test-results/junit.xml" \
|
||||||
|
--form "CI_COMMIT_SHA=${CI_COMMIT_SHA:-}" \
|
||||||
|
--form "CI_PR_NUMBER=${CI_PR_NUMBER:-}" \
|
||||||
|
--form "GITHUB_BASE_REF=${GITHUB_BASE_REF:-}" \
|
||||||
|
--form "GITHUB_EVENT_NAME=${GITHUB_EVENT_NAME:-}" \
|
||||||
|
--form "GITHUB_HEAD_REF=${GITHUB_HEAD_REF:-}" \
|
||||||
|
--form "GITHUB_REF_NAME=${GITHUB_REF_NAME:-}" \
|
||||||
|
--form "GITHUB_REF=${GITHUB_REF:-}" \
|
||||||
|
--form "GITHUB_SHA=${GITHUB_SHA:-}" \
|
||||||
|
--form "GITHUB_WORKFLOW=${GITHUB_WORKFLOW:-}" \
|
||||||
|
--form "RUNNER_ARCH=${RUNNER_ARCH:-}" \
|
||||||
${TAB_API_URL}/api/results/bulk
|
${TAB_API_URL}/api/results/bulk
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Sharing updated report"
|
||||||
|
curl --silent --request POST \
|
||||||
|
--header "Content-Type: application/json" \
|
||||||
|
--header "X-API-Key: ${TAB_API_KEY}" \
|
||||||
|
--data "{
|
||||||
|
\"project\": \"${project}\",
|
||||||
|
\"branch\": \"${branch}\",
|
||||||
|
\"commit\": \"${commit}\"
|
||||||
|
}" \
|
||||||
|
${TAB_API_URL}/api/share
|
||||||
|
78
.github/workflows/build-apps.yml
vendored
@ -7,14 +7,13 @@ on:
|
|||||||
- main
|
- main
|
||||||
tags:
|
tags:
|
||||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||||
- 'nightly-v[0-9]+.[0-9]+.[0-9]+'
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
IS_RELEASE: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'v') }}
|
IS_RELEASE: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'v') }}
|
||||||
IS_NIGHTLY: ${{ github.ref_type == 'tag' && startsWith(github.ref_name, 'nightly-v') }}
|
IS_NIGHTLY: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@ -95,7 +94,9 @@ jobs:
|
|||||||
- name: Set nightly version, product name, release notes, and icons
|
- name: Set nightly version, product name, release notes, and icons
|
||||||
if: ${{ env.IS_NIGHTLY == 'true' }}
|
if: ${{ env.IS_NIGHTLY == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
export VERSION=${GITHUB_REF_NAME#nightly-v}
|
COMMIT=$(git rev-parse --short HEAD)
|
||||||
|
DATE=$(date +'%-y.%-m.%-d')
|
||||||
|
export VERSION=$DATE-main.$COMMIT
|
||||||
npm run files:set-version
|
npm run files:set-version
|
||||||
npm run files:flip-to-nightly
|
npm run files:flip-to-nightly
|
||||||
|
|
||||||
@ -122,18 +123,6 @@ jobs:
|
|||||||
- id: export_notes
|
- id: export_notes
|
||||||
run: echo "notes=`cat release-notes.md`" >> "$GITHUB_OUTPUT"
|
run: echo "notes=`cat release-notes.md`" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Prepare electron-builder.yml file for updater test
|
|
||||||
if: ${{ env.IS_RELEASE == 'true' }}
|
|
||||||
run: |
|
|
||||||
yq -i '.publish[0].url = "https://dl.zoo.dev/releases/modeling-app/updater-test"' electron-builder.yml
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
if: ${{ env.IS_RELEASE == 'true' }}
|
|
||||||
with:
|
|
||||||
name: prepared-files-updater-test
|
|
||||||
path: |
|
|
||||||
electron-builder.yml
|
|
||||||
|
|
||||||
|
|
||||||
build-apps:
|
build-apps:
|
||||||
needs: [prepare-files]
|
needs: [prepare-files]
|
||||||
@ -258,55 +247,13 @@ jobs:
|
|||||||
|
|
||||||
# TODO: add the 'Build for Mac TestFlight (nightly)' stage back
|
# TODO: add the 'Build for Mac TestFlight (nightly)' stage back
|
||||||
|
|
||||||
# The steps below are for updater-test builds, only on release
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
|
||||||
if: ${{ env.IS_RELEASE == 'true' }}
|
|
||||||
name: prepared-files-updater-test
|
|
||||||
|
|
||||||
- name: Copy updated electron-builder.yml file for updater test
|
|
||||||
if: ${{ env.IS_RELEASE == 'true' }}
|
|
||||||
run: |
|
|
||||||
ls -R prepared-files-updater-test
|
|
||||||
cp prepared-files-updater-test/electron-builder.yml electron-builder.yml
|
|
||||||
|
|
||||||
- name: Build the app (updater-test)
|
|
||||||
if: ${{ env.IS_RELEASE == 'true' }}
|
|
||||||
env:
|
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
||||||
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
||||||
CSC_LINK: ${{ secrets.APPLE_CERTIFICATE }}
|
|
||||||
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
||||||
CSC_KEYCHAIN: ${{ secrets.APPLE_SIGNING_IDENTITY }}
|
|
||||||
WINDOWS_CERTIFICATE_THUMBPRINT: ${{ secrets.WINDOWS_CERTIFICATE_THUMBPRINT }}
|
|
||||||
run: npm run tronb:package:prod
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
if: ${{ env.IS_RELEASE == 'true' }}
|
|
||||||
with:
|
|
||||||
name: updater-test-arm64-${{ matrix.platform }}
|
|
||||||
path: |
|
|
||||||
out/*-arm64-win.exe
|
|
||||||
out/*-arm64-mac.dmg
|
|
||||||
out/*-arm64-linux.AppImage
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
if: ${{ env.IS_RELEASE == 'true' }}
|
|
||||||
with:
|
|
||||||
name: updater-test-x64-${{ matrix.platform }}
|
|
||||||
path: |
|
|
||||||
out/*-x64-win.exe
|
|
||||||
out/*-x64-mac.dmg
|
|
||||||
out/*-x86_64-linux.AppImage
|
|
||||||
|
|
||||||
|
|
||||||
upload-apps-release:
|
upload-apps-release:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
if: ${{ github.ref_type == 'tag' }}
|
# Equivalent to IS_RELEASE || IS_NIGHTLY (but we can't access those env vars here)
|
||||||
|
if: ${{ (github.ref_type == 'tag' && startsWith(github.ref_name, 'v')) || (github.event_name == 'push' && github.ref == 'refs/heads/main') }}
|
||||||
env:
|
env:
|
||||||
VERSION_NO_V: ${{ needs.prepare-files.outputs.version }}
|
VERSION_NO_V: ${{ needs.prepare-files.outputs.version }}
|
||||||
VERSION: ${{ format('v{0}', needs.prepare-files.outputs.version) }}
|
VERSION: ${{ format('v{0}', needs.prepare-files.outputs.version) }}
|
||||||
@ -412,17 +359,6 @@ jobs:
|
|||||||
- name: List artifacts
|
- name: List artifacts
|
||||||
run: "ls -R out"
|
run: "ls -R out"
|
||||||
|
|
||||||
- name: Set more complete nightly release notes
|
|
||||||
if: ${{ env.IS_NIGHTLY == 'true' }}
|
|
||||||
run: |
|
|
||||||
# Note: preferred going this way instead of a full clone in the checkout step,
|
|
||||||
# see https://github.com/actions/checkout/issues/1471
|
|
||||||
git fetch --prune --unshallow --tags
|
|
||||||
export TAG="nightly-${VERSION}"
|
|
||||||
export PREVIOUS_TAG=$(git tag --list --sort=-committerdate "nightly-v[0-9]*" | head -n2 | tail -n1)
|
|
||||||
export NOTES=$(./scripts/get-nightly-changelog.sh)
|
|
||||||
npm run files:set-notes
|
|
||||||
|
|
||||||
- name: Authenticate to Google Cloud
|
- name: Authenticate to Google Cloud
|
||||||
if: ${{ env.IS_NIGHTLY == 'true' }}
|
if: ${{ env.IS_NIGHTLY == 'true' }}
|
||||||
uses: 'google-github-actions/auth@v2.1.8'
|
uses: 'google-github-actions/auth@v2.1.8'
|
||||||
|
56
.github/workflows/build-wasm.yml
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
name: Build WASM
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
npm-build-wasm:
|
||||||
|
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Use correct Rust toolchain
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
|
|
||||||
|
- name: Install rust
|
||||||
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
cache: false # configured below
|
||||||
|
|
||||||
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
|
with:
|
||||||
|
tool: wasm-pack
|
||||||
|
|
||||||
|
- name: Use Rust cache
|
||||||
|
uses: Swatinem/rust-cache@v2
|
||||||
|
with:
|
||||||
|
workspaces: './rust'
|
||||||
|
|
||||||
|
- name: Build Wasm
|
||||||
|
shell: bash
|
||||||
|
run: npm run build:wasm
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: prepared-wasm
|
||||||
|
path: |
|
||||||
|
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: prepared-ts-rs-bindings
|
||||||
|
path: |
|
||||||
|
rust/kcl-lib/bindings/*
|
52
.github/workflows/cargo-test.yml
vendored
@ -155,7 +155,7 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
- name: Install rust
|
- name: Install Rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: false # Configured below.
|
cache: false # Configured below.
|
||||||
@ -188,6 +188,56 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TAB_API_URL: ${{ secrets.TAB_API_URL }}
|
TAB_API_URL: ${{ secrets.TAB_API_URL }}
|
||||||
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
TAB_API_KEY: ${{ secrets.TAB_API_KEY }}
|
||||||
|
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
|
CI_PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
run-internal-kcl-samples:
|
||||||
|
name: cargo test (internal-kcl-samples)
|
||||||
|
runs-on:
|
||||||
|
- runs-on=${{ github.run_id }}
|
||||||
|
- runner=32cpu-linux-x64
|
||||||
|
- extras=s3-cache
|
||||||
|
steps:
|
||||||
|
- uses: runs-on/action@v1
|
||||||
|
- uses: actions/create-github-app-token@v1
|
||||||
|
id: app-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||||
|
private-key: ${{ secrets.MODELING_APP_GH_APP_PRIVATE_KEY }}
|
||||||
|
owner: ${{ github.repository_owner }}
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ steps.app-token.outputs.token }}
|
||||||
|
- name: Use correct Rust toolchain
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
|
- name: Install Rust
|
||||||
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
|
with:
|
||||||
|
cache: false # Configured below.
|
||||||
|
- name: Start Vector
|
||||||
|
run: .github/ci-cd-scripts/start-vector-ubuntu.sh
|
||||||
|
env:
|
||||||
|
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
||||||
|
OS_NAME: ${{ env.OS_NAME }}
|
||||||
|
- uses: taiki-e/install-action@nextest
|
||||||
|
- name: Download internal KCL samples
|
||||||
|
run: git clone --depth=1 https://x-access-token:${{ secrets.GH_PAT_KCL_SAMPLES_INTERNAL }}@github.com/KittyCAD/kcl-samples-internal public/kcl-samples/internal
|
||||||
|
- name: Run tests
|
||||||
|
shell: bash
|
||||||
|
run: |-
|
||||||
|
cd rust/kcl-lib
|
||||||
|
cargo nextest run \
|
||||||
|
--retries=10 --no-fail-fast --features artifact-graph --profile=ci \
|
||||||
|
internal \
|
||||||
|
2>&1 | tee /tmp/github-actions.log
|
||||||
|
env:
|
||||||
|
TWENTY_TWENTY: overwrite
|
||||||
|
INSTA_UPDATE: always
|
||||||
|
EXPECTORATE: overwrite
|
||||||
|
KITTYCAD_API_TOKEN: ${{secrets.KITTYCAD_API_TOKEN_DEV}}
|
||||||
|
ZOO_HOST: https://api.dev.zoo.dev
|
||||||
|
MODELING_APP_INTERNAL_SAMPLES_SECRET: ${{secrets.MODELING_APP_INTERNAL_SAMPLES_SECRET}}
|
||||||
run-wasm-tests:
|
run-wasm-tests:
|
||||||
name: Run wasm tests
|
name: Run wasm tests
|
||||||
strategy:
|
strategy:
|
||||||
|
47
.github/workflows/check-exampleKcl.yml
vendored
@ -1,47 +0,0 @@
|
|||||||
name: Check Onboarding KCL
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize]
|
|
||||||
paths:
|
|
||||||
- 'src/lib/exampleKcl.ts'
|
|
||||||
- 'public/kcl-samples/bracket/main.kcl'
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
comment:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Comment on PR
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const message = '`public/kcl-samples/bracket/main.kcl` or `src/lib/exampleKcl.ts` has been updated in this PR, please review and update the `src/routes/onboarding`, if needed.';
|
|
||||||
const issue_number = context.payload.pull_request.number;
|
|
||||||
const owner = context.repo.owner;
|
|
||||||
const repo = context.repo.repo;
|
|
||||||
|
|
||||||
const { data: comments } = await github.rest.issues.listComments({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
issue_number
|
|
||||||
});
|
|
||||||
|
|
||||||
const commentExists = comments.some(comment => comment.body === message);
|
|
||||||
|
|
||||||
if (!commentExists) {
|
|
||||||
// Post a comment on the PR
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
issue_number,
|
|
||||||
body: message,
|
|
||||||
});
|
|
||||||
}
|
|
150
.github/workflows/e2e-tests.yml
vendored
@ -18,73 +18,13 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
conditions:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
significant: ${{ steps.path-changes.outputs.significant }}
|
|
||||||
should-run: ${{ steps.should-run.outputs.should-run }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Fetch the base branch
|
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
|
||||||
run: git fetch origin ${{ github.base_ref }} --depth=1
|
|
||||||
|
|
||||||
- name: Check for path changes
|
|
||||||
id: path-changes
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Manual runs or push should run all tests.
|
|
||||||
if [[ ${{ github.event_name }} != 'pull_request' ]]; then
|
|
||||||
echo "significant=true" >> $GITHUB_OUTPUT
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
changed_files=$(git diff --name-only origin/${{ github.base_ref }})
|
|
||||||
echo "$changed_files"
|
|
||||||
if grep -Evq '^README.md|^public/kcl-samples/|^rust/kcl-lib/tests/kcl_samples/' <<< "$changed_files" ; then
|
|
||||||
echo "significant=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "significant=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Should run
|
|
||||||
id: should-run
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
# We should run when this is a scheduled run or if there are
|
|
||||||
# significant changes in the diff.
|
|
||||||
if [[ ${{ github.event_name }} == 'schedule' || ${{ steps.path-changes.outputs.significant }} == 'true' ]]; then
|
|
||||||
echo "should-run=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "should-run=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Display conditions
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
# For debugging purposes
|
|
||||||
set -euo pipefail
|
|
||||||
echo "GITHUB_REF: $GITHUB_REF"
|
|
||||||
echo "GITHUB_HEAD_REF: $GITHUB_HEAD_REF"
|
|
||||||
echo "GITHUB_BASE_REF: $GITHUB_BASE_REF"
|
|
||||||
echo "significant: ${{ steps.path-changes.outputs.significant }}"
|
|
||||||
echo "should-run: ${{ steps.should-run.outputs.should-run }}"
|
|
||||||
|
|
||||||
prepare-wasm:
|
prepare-wasm:
|
||||||
# separate job on Ubuntu to build or fetch the wasm blob once on the fastest runner
|
# separate job on Ubuntu to build or fetch the wasm blob once on the fastest runner
|
||||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||||
needs: conditions
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
|
|
||||||
- id: filter
|
- id: filter
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
name: Check for Rust changes
|
name: Check for Rust changes
|
||||||
uses: dorny/paths-filter@v3
|
uses: dorny/paths-filter@v3
|
||||||
with:
|
with:
|
||||||
@ -93,18 +33,16 @@ jobs:
|
|||||||
- 'rust/**'
|
- 'rust/**'
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Download Wasm Cache
|
- name: Download Wasm cache
|
||||||
id: download-wasm
|
id: download-wasm
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && github.event_name != 'schedule' && steps.filter.outputs.rust == 'false' }}
|
if: ${{ github.event_name != 'schedule' && steps.filter.outputs.rust == 'false' }}
|
||||||
uses: dawidd6/action-download-artifact@v7
|
uses: dawidd6/action-download-artifact@v7
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
@ -114,9 +52,8 @@ jobs:
|
|||||||
branch: main
|
branch: main
|
||||||
path: rust/kcl-wasm-lib/pkg
|
path: rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
- name: Build WASM condition
|
- name: Build Wasm condition
|
||||||
id: wasm
|
id: wasm
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: |
|
run: |
|
||||||
set -euox pipefail
|
set -euox pipefail
|
||||||
# Build wasm if this is a scheduled run, there are Rust changes, or
|
# Build wasm if this is a scheduled run, there are Rust changes, or
|
||||||
@ -128,35 +65,34 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
- name: Use correct Rust toolchain
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
||||||
|
|
||||||
- name: Install rust
|
- name: Install Rust
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: false # Configured below.
|
cache: false # Configured below.
|
||||||
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||||
with:
|
with:
|
||||||
tool: wasm-pack
|
tool: wasm-pack
|
||||||
|
|
||||||
- name: Rust Cache
|
- name: Use Rust cache
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
with:
|
with:
|
||||||
workspaces: './rust'
|
workspaces: './rust'
|
||||||
|
|
||||||
- name: Build Wasm
|
- name: Build Wasm
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && steps.wasm.outputs.should-build-wasm == 'true' }}
|
if: ${{ steps.wasm.outputs.should-build-wasm == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: npm run build:wasm
|
run: npm run build:wasm
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
with:
|
with:
|
||||||
name: prepared-wasm
|
name: prepared-wasm
|
||||||
path: |
|
path: |
|
||||||
@ -165,10 +101,9 @@ jobs:
|
|||||||
snapshots:
|
snapshots:
|
||||||
name: playwright:snapshots:ubuntu
|
name: playwright:snapshots:ubuntu
|
||||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
||||||
needs: [conditions, prepare-wasm]
|
needs: [prepare-wasm]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/create-github-app-token@v1
|
- uses: actions/create-github-app-token@v1
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
id: app-token
|
id: app-token
|
||||||
with:
|
with:
|
||||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
||||||
@ -176,16 +111,13 @@ jobs:
|
|||||||
owner: ${{ github.repository_owner }}
|
owner: ${{ github.repository_owner }}
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.app-token.outputs.token }}
|
token: ${{ steps.app-token.outputs.token }}
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
name: prepared-wasm
|
name: prepared-wasm
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
- name: Copy prepared Wasm
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: |
|
run: |
|
||||||
ls -R prepared-wasm
|
ls -R prepared-wasm
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
@ -193,34 +125,25 @@ jobs:
|
|||||||
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
id: deps-install
|
id: deps-install
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Cache Playwright Browsers
|
- name: Cache browsers
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/ms-playwright/
|
~/.cache/ms-playwright/
|
||||||
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
|
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install browsers
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: npm run playwright install --with-deps
|
run: npm run playwright install --with-deps
|
||||||
|
|
||||||
- name: build web
|
- name: Capture snapshots
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: npm run tronb:vite:dev
|
|
||||||
|
|
||||||
- name: Run ubuntu/chrome snapshots
|
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
uses: nick-fields/retry@v3.0.2
|
uses: nick-fields/retry@v3.0.2
|
||||||
with:
|
with:
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -236,7 +159,7 @@ jobs:
|
|||||||
TARGET: web
|
TARGET: web
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
if: ${{ !cancelled() && (success() || failure()) }}
|
||||||
with:
|
with:
|
||||||
name: playwright-report-ubuntu-snapshot-${{ github.sha }}
|
name: playwright-report-ubuntu-snapshot-${{ github.sha }}
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
@ -244,8 +167,8 @@ jobs:
|
|||||||
retention-days: 30
|
retention-days: 30
|
||||||
overwrite: true
|
overwrite: true
|
||||||
|
|
||||||
- name: Check for changes
|
- name: Check diff
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && github.ref != 'refs/heads/main' }}
|
if: ${{ github.ref != 'refs/heads/main' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
id: git-check
|
id: git-check
|
||||||
run: |
|
run: |
|
||||||
@ -255,9 +178,8 @@ jobs:
|
|||||||
else echo "modified=false" >> $GITHUB_OUTPUT
|
else echo "modified=false" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Commit changes, if any
|
- name: Commit changes
|
||||||
# TODO: find a more reliable way to detect visual changes
|
if: ${{ steps.git-check.outputs.modified == 'true' }}
|
||||||
if: ${{ false && needs.conditions.outputs.should-run == 'true' && steps.git-check.outputs.modified == 'true' }}
|
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
git add e2e/playwright/snapshot-tests.spec.ts-snapshots e2e/playwright/snapshots
|
||||||
@ -267,12 +189,12 @@ jobs:
|
|||||||
git fetch origin
|
git fetch origin
|
||||||
echo ${{ github.head_ref }}
|
echo ${{ github.head_ref }}
|
||||||
git checkout ${{ github.head_ref }}
|
git checkout ${{ github.head_ref }}
|
||||||
git commit -m "A snapshot a day keeps the bugs away! 📷🐛" || true
|
git commit --message "Update snapshots" || true
|
||||||
git push
|
git push
|
||||||
git push origin ${{ github.head_ref }}
|
git push origin ${{ github.head_ref }}
|
||||||
|
|
||||||
electron:
|
electron:
|
||||||
needs: [conditions, prepare-wasm]
|
needs: [prepare-wasm]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
env:
|
env:
|
||||||
OS_NAME: ${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}
|
OS_NAME: ${{ contains(matrix.os, 'ubuntu') && 'ubuntu' || (contains(matrix.os, 'windows') && 'windows' || 'macos') }}
|
||||||
@ -308,21 +230,24 @@ jobs:
|
|||||||
shardTotal: 8
|
shardTotal: 8
|
||||||
- os: namespace-profile-macos-8-cores
|
- os: namespace-profile-macos-8-cores
|
||||||
shardIndex: 1
|
shardIndex: 1
|
||||||
shardTotal: 1
|
shardTotal: 2
|
||||||
|
- os: namespace-profile-macos-8-cores
|
||||||
|
shardIndex: 2
|
||||||
|
shardTotal: 2
|
||||||
- os: windows-latest-8-cores
|
- os: windows-latest-8-cores
|
||||||
shardIndex: 1
|
shardIndex: 1
|
||||||
shardTotal: 1
|
shardTotal: 2
|
||||||
|
- os: windows-latest-8-cores
|
||||||
|
shardIndex: 2
|
||||||
|
shardTotal: 2
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
name: prepared-wasm
|
name: prepared-wasm
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
- name: Copy prepared wasm
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: |
|
run: |
|
||||||
ls -R prepared-wasm
|
ls -R prepared-wasm
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
@ -330,18 +255,15 @@ jobs:
|
|||||||
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
id: deps-install
|
id: deps-install
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: npm install
|
run: npm install
|
||||||
|
|
||||||
- name: Cache Playwright Browsers
|
- name: Cache Playwright Browsers
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@ -349,22 +271,20 @@ jobs:
|
|||||||
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
|
key: ${{ runner.os }}-playwright-${{ hashFiles('package-lock.json') }}
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: npm run playwright install --with-deps
|
run: npm run playwright install --with-deps
|
||||||
|
|
||||||
- name: Build web
|
- name: Build web
|
||||||
if: needs.conditions.outputs.should-run == 'true'
|
|
||||||
run: npm run tronb:vite:dev
|
run: npm run tronb:vite:dev
|
||||||
|
|
||||||
- name: Start Vector
|
- name: Start Vector
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !contains(matrix.os, 'windows') }}
|
if: ${{ !contains(matrix.os, 'windows') }}
|
||||||
run: .github/ci-cd-scripts/start-vector-${{ env.OS_NAME }}.sh
|
run: .github/ci-cd-scripts/start-vector-${{ env.OS_NAME }}.sh
|
||||||
env:
|
env:
|
||||||
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
GH_ACTIONS_AXIOM_TOKEN: ${{ secrets.GH_ACTIONS_AXIOM_TOKEN }}
|
||||||
OS_NAME: ${{ env.OS_NAME }}
|
OS_NAME: ${{ env.OS_NAME }}
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && (success() || failure()) }}
|
if: ${{ !cancelled() && (success() || failure()) }}
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
name: test-results-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
name: test-results-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||||
@ -372,7 +292,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Run playwright/electron flow (with retries)
|
- name: Run playwright/electron flow (with retries)
|
||||||
id: retry
|
id: retry
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && !cancelled() && steps.deps-install.outcome == 'success' }}
|
if: ${{ !cancelled() && steps.deps-install.outcome == 'success' }}
|
||||||
uses: nick-fields/retry@v3.0.2
|
uses: nick-fields/retry@v3.0.2
|
||||||
with:
|
with:
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -389,7 +309,7 @@ jobs:
|
|||||||
TARGET: desktop
|
TARGET: desktop
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: test-results-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
name: test-results-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||||
path: test-results/
|
path: test-results/
|
||||||
@ -398,7 +318,7 @@ jobs:
|
|||||||
overwrite: true
|
overwrite: true
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
if: ${{ needs.conditions.outputs.should-run == 'true' && always() }}
|
if: always()
|
||||||
with:
|
with:
|
||||||
name: playwright-report-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
name: playwright-report-${{ env.OS_NAME }}-${{ matrix.shardIndex }}-${{ github.sha }}
|
||||||
path: playwright-report/
|
path: playwright-report/
|
||||||
|
61
.github/workflows/kcl-language-server.yml
vendored
@ -21,14 +21,11 @@ on:
|
|||||||
- '**.rs'
|
- '**.rs'
|
||||||
- .github/workflows/kcl-language-server.yml
|
- .github/workflows/kcl-language-server.yml
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: 0
|
CARGO_INCREMENTAL: 0
|
||||||
CARGO_NET_RETRY: 10
|
CARGO_NET_RETRY: 10
|
||||||
@ -38,10 +35,9 @@ env:
|
|||||||
MACOSX_DEPLOYMENT_TARGET: 10.15
|
MACOSX_DEPLOYMENT_TARGET: 10.15
|
||||||
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
|
||||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: vscode tests
|
name: kcl-language-server (vscode tests)
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@ -77,8 +73,7 @@ jobs:
|
|||||||
include:
|
include:
|
||||||
- os: windows-latest
|
- os: windows-latest
|
||||||
target: x86_64-pc-windows-msvc
|
target: x86_64-pc-windows-msvc
|
||||||
code-target:
|
code-target: win32-x64
|
||||||
win32-x64
|
|
||||||
#- os: windows-latest
|
#- os: windows-latest
|
||||||
#target: i686-pc-windows-msvc
|
#target: i686-pc-windows-msvc
|
||||||
#code-target:
|
#code-target:
|
||||||
@ -88,8 +83,7 @@ jobs:
|
|||||||
#code-target: win32-arm64
|
#code-target: win32-arm64
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
target: x86_64-unknown-linux-gnu
|
target: x86_64-unknown-linux-gnu
|
||||||
code-target:
|
code-target: linux-x64
|
||||||
linux-x64
|
|
||||||
#- os: ubuntu-latest
|
#- os: ubuntu-latest
|
||||||
#target: aarch64-unknown-linux-musl
|
#target: aarch64-unknown-linux-musl
|
||||||
#code-target: linux-arm64
|
#code-target: linux-arm64
|
||||||
@ -105,41 +99,33 @@ jobs:
|
|||||||
- os: macos-latest
|
- os: macos-latest
|
||||||
target: aarch64-apple-darwin
|
target: aarch64-apple-darwin
|
||||||
code-target: darwin-arm64
|
code-target: darwin-arm64
|
||||||
|
name: kcl-language-server build-release (${{ matrix.target }})
|
||||||
name: build-release (${{ matrix.target }})
|
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
container: ${{ matrix.container }}
|
container: ${{ matrix.container }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RA_TARGET: ${{ matrix.target }}
|
RA_TARGET: ${{ matrix.target }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: ${{ env.FETCH_DEPTH }}
|
fetch-depth: ${{ env.FETCH_DEPTH }}
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
- name: Use correct Rust toolchain
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
rm rust/rust-toolchain.toml
|
rm rust/rust-toolchain.toml
|
||||||
|
|
||||||
- name: Install rust
|
- name: Install rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: rust
|
cache: rust
|
||||||
components: rust-src
|
components: rust-src
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
|
|
||||||
- name: Update apt repositories
|
- name: Update apt repositories
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf' || matrix.os == 'ubuntu-latest'
|
if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf' || matrix.os == 'ubuntu-latest'
|
||||||
run: sudo apt-get update
|
run: sudo apt-get update
|
||||||
|
|
||||||
- if: ${{ matrix.os == 'ubuntu-latest' }}
|
- if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||||
name: Install deps
|
name: Install deps
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -164,64 +150,53 @@ jobs:
|
|||||||
zlib1g-dev
|
zlib1g-dev
|
||||||
|
|
||||||
cargo install cross
|
cargo install cross
|
||||||
|
|
||||||
- name: Install AArch64 target toolchain
|
- name: Install AArch64 target toolchain
|
||||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||||
run: sudo apt-get install gcc-aarch64-linux-gnu
|
run: sudo apt-get install gcc-aarch64-linux-gnu
|
||||||
|
|
||||||
- name: Install ARM target toolchain
|
- name: Install ARM target toolchain
|
||||||
if: matrix.target == 'arm-unknown-linux-gnueabihf'
|
if: matrix.target == 'arm-unknown-linux-gnueabihf'
|
||||||
run: sudo apt-get install gcc-arm-linux-gnueabihf
|
run: sudo apt-get install gcc-arm-linux-gnueabihf
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
# npm will symlink which will cause issues w tarballing later
|
# npm will symlink which will cause issues w tarballing later
|
||||||
yarn install
|
yarn install
|
||||||
|
|
||||||
- name: Package Extension (release)
|
- name: Package Extension (release)
|
||||||
if: startsWith(github.event.ref, 'refs/tags/')
|
if: startsWith(github.event.ref, 'refs/tags/')
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }}
|
npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }}
|
||||||
|
|
||||||
- name: Package Extension (nightly)
|
- name: Package Extension (nightly)
|
||||||
if: startsWith(github.event.ref, 'refs/tags/') == false
|
if: startsWith(github.event.ref, 'refs/tags/') == false
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} --pre-release
|
npx vsce package --yarn -o "../build/kcl-language-server-${{ matrix.code-target }}.vsix" --target ${{ matrix.code-target }} --pre-release
|
||||||
|
|
||||||
- name: remove server
|
- name: remove server
|
||||||
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
rm -rf server
|
rm -rf server
|
||||||
|
|
||||||
- name: Package Extension (no server, release)
|
- name: Package Extension (no server, release)
|
||||||
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/')
|
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/')
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix
|
npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix
|
||||||
|
|
||||||
- name: Package Extension (no server, nightly)
|
- name: Package Extension (no server, nightly)
|
||||||
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/') == false
|
if: matrix.target == 'x86_64-unknown-linux-gnu' && startsWith(github.event.ref, 'refs/tags/') == false
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix --pre-release
|
npx vsce package --yarn -o ../build/kcl-language-server-no-server.vsix --pre-release
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-${{ matrix.target }}
|
name: release-${{ matrix.target }}
|
||||||
path: ./rust/build
|
path: ./rust/build
|
||||||
|
|
||||||
build-release-x86_64-unknown-linux-musl:
|
build-release-x86_64-unknown-linux-musl:
|
||||||
name: build-release (x86_64-unknown-linux-musl)
|
name: kcl-language-server build-release (x86_64-unknown-linux-musl)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
RA_TARGET: x86_64-unknown-linux-musl
|
RA_TARGET: x86_64-unknown-linux-musl
|
||||||
@ -231,7 +206,6 @@ jobs:
|
|||||||
image: alpine:latest
|
image: alpine:latest
|
||||||
volumes:
|
volumes:
|
||||||
- /usr/local/cargo/registry:/usr/local/cargo/registry
|
- /usr/local/cargo/registry:/usr/local/cargo/registry
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
@ -245,55 +219,46 @@ jobs:
|
|||||||
nodejs \
|
nodejs \
|
||||||
npm \
|
npm \
|
||||||
yarn
|
yarn
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: ${{ env.FETCH_DEPTH }}
|
fetch-depth: ${{ env.FETCH_DEPTH }}
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
- name: Use correct Rust toolchain
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
rm rust/rust-toolchain.toml
|
rm rust/rust-toolchain.toml
|
||||||
|
|
||||||
- name: Install rust
|
- name: Install rust
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||||
with:
|
with:
|
||||||
cache: rust
|
cache: rust
|
||||||
components: rust-src
|
components: rust-src
|
||||||
target: ${{ matrix.target }}
|
target: ${{ matrix.target }}
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
cargo kcl-language-server-release build --client-patch-version ${{ github.run_number }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
# npm will symlink which will cause issues w tarballing later
|
# npm will symlink which will cause issues w tarballing later
|
||||||
yarn install
|
yarn install
|
||||||
|
|
||||||
- name: Package Extension (release)
|
- name: Package Extension (release)
|
||||||
if: startsWith(github.event.ref, 'refs/tags/')
|
if: startsWith(github.event.ref, 'refs/tags/')
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64
|
npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64
|
||||||
|
|
||||||
- name: Package Extension (release)
|
- name: Package Extension (release)
|
||||||
if: startsWith(github.event.ref, 'refs/tags/') == false
|
if: startsWith(github.event.ref, 'refs/tags/') == false
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64 --pre-release
|
npx vsce package --yarn -o "../build/kcl-language-server-alpine-x64.vsix" --target alpine-x64 --pre-release
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-x86_64-unknown-linux-musl
|
name: release-x86_64-unknown-linux-musl
|
||||||
path: ./rust/build
|
path: ./rust/build
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
name: publish
|
name: kcl-language-server (publish)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: ["build-release", "build-release-x86_64-unknown-linux-musl"]
|
needs: ["build-release", "build-release-x86_64-unknown-linux-musl"]
|
||||||
if: startsWith(github.event.ref, 'refs/tags')
|
if: startsWith(github.event.ref, 'refs/tags')
|
||||||
@ -301,22 +266,17 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
steps:
|
steps:
|
||||||
- run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
- run: echo "TAG=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- run: 'echo "TAG: $TAG"'
|
- run: 'echo "TAG: $TAG"'
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: ${{ env.FETCH_DEPTH }}
|
fetch-depth: ${{ env.FETCH_DEPTH }}
|
||||||
|
|
||||||
- name: Install Nodejs
|
- name: Install Nodejs
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: ".nvmrc"
|
node-version-file: ".nvmrc"
|
||||||
|
|
||||||
- run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
- run: echo "HEAD_SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
||||||
- run: 'echo "HEAD_SHA: $HEAD_SHA"'
|
- run: 'echo "HEAD_SHA: $HEAD_SHA"'
|
||||||
|
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-aarch64-apple-darwin
|
name: release-aarch64-apple-darwin
|
||||||
@ -344,8 +304,7 @@ jobs:
|
|||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release-x86_64-pc-windows-msvc
|
name: release-x86_64-pc-windows-msvc
|
||||||
path:
|
path: rust/build
|
||||||
rust/build
|
|
||||||
#- uses: actions/download-artifact@v4
|
#- uses: actions/download-artifact@v4
|
||||||
#with:
|
#with:
|
||||||
#name: release-i686-pc-windows-msvc
|
#name: release-i686-pc-windows-msvc
|
||||||
@ -356,21 +315,18 @@ jobs:
|
|||||||
#name: release-aarch64-pc-windows-msvc
|
#name: release-aarch64-pc-windows-msvc
|
||||||
#path: rust/build
|
#path: rust/build
|
||||||
- run: ls -al ./rust/build
|
- run: ls -al ./rust/build
|
||||||
|
|
||||||
- name: Publish Release
|
- name: Publish Release
|
||||||
uses: ./.github/actions/github-release
|
uses: ./.github/actions/github-release
|
||||||
with:
|
with:
|
||||||
files: "rust/build/*"
|
files: "rust/build/*"
|
||||||
name: ${{ env.TAG }}
|
name: ${{ env.TAG }}
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: move files to dir for upload
|
- name: move files to dir for upload
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd rust
|
cd rust
|
||||||
mkdir -p releases/language-server/${{ env.TAG }}
|
mkdir -p releases/language-server/${{ env.TAG }}
|
||||||
cp -r build/* releases/language-server/${{ env.TAG }}
|
cp -r build/* releases/language-server/${{ env.TAG }}
|
||||||
|
|
||||||
- name: "Authenticate to Google Cloud"
|
- name: "Authenticate to Google Cloud"
|
||||||
uses: "google-github-actions/auth@v2.1.8"
|
uses: "google-github-actions/auth@v2.1.8"
|
||||||
with:
|
with:
|
||||||
@ -385,15 +341,12 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: rust/releases
|
path: rust/releases
|
||||||
destination: dl.kittycad.io
|
destination: dl.kittycad.io
|
||||||
|
|
||||||
- run: rm rust/build/kcl-language-server-no-server.vsix
|
- run: rm rust/build/kcl-language-server-no-server.vsix
|
||||||
|
|
||||||
- name: Publish Extension (Code Marketplace, release)
|
- name: Publish Extension (Code Marketplace, release)
|
||||||
# token from https://dev.azure.com/kcl-language-server/
|
# token from https://dev.azure.com/kcl-language-server/
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
npx vsce publish --pat ${{ secrets.VSCE_PAT }} --packagePath ../build/kcl-language-server-*.vsix
|
npx vsce publish --pat ${{ secrets.VSCE_PAT }} --packagePath ../build/kcl-language-server-*.vsix
|
||||||
|
|
||||||
- name: Publish Extension (OpenVSX, release)
|
- name: Publish Extension (OpenVSX, release)
|
||||||
run: |
|
run: |
|
||||||
cd rust/kcl-language-server
|
cd rust/kcl-language-server
|
||||||
|
14
.github/workflows/kcl-python-bindings.yml
vendored
@ -4,7 +4,6 @@
|
|||||||
# maturin generate-ci github
|
# maturin generate-ci github
|
||||||
#
|
#
|
||||||
name: kcl-python-bindings
|
name: kcl-python-bindings
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@ -27,16 +26,14 @@ on:
|
|||||||
- '**.rs'
|
- '**.rs'
|
||||||
- .github/workflows/kcl-python-bindings.yml
|
- .github/workflows/kcl-python-bindings.yml
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
linux-x86_64:
|
linux-x86_64:
|
||||||
|
name: kcl-python-bindings (linux-x86_64)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -58,8 +55,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-linux-x86_64
|
name: wheels-linux-x86_64
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
|
name: kcl-python-bindings (windows)
|
||||||
runs-on: windows-16-cores
|
runs-on: windows-16-cores
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -84,8 +81,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-windows-${{ matrix.target }}
|
name: wheels-windows-${{ matrix.target }}
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
|
name: kcl-python-bindings (macos)
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
@ -110,8 +107,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-macos-${{ matrix.target }}
|
name: wheels-macos-${{ matrix.target }}
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
name: kcl-python-bindings (test)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -127,8 +124,8 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
KITTYCAD_API_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
||||||
ZOO_HOST: https://api.dev.zoo.dev
|
ZOO_HOST: https://api.dev.zoo.dev
|
||||||
|
|
||||||
sdist:
|
sdist:
|
||||||
|
name: kcl-python-bindings (sdist)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@ -151,7 +148,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: wheels-sdist
|
name: wheels-sdist
|
||||||
path: rust/kcl-python-bindings/dist
|
path: rust/kcl-python-bindings/dist
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
161
.github/workflows/static-analysis.yml
vendored
@ -28,53 +28,7 @@ jobs:
|
|||||||
- run: npm run fmt:check
|
- run: npm run fmt:check
|
||||||
|
|
||||||
npm-build-wasm:
|
npm-build-wasm:
|
||||||
# Build the wasm blob once on the fastest runner.
|
uses: ./.github/workflows/build-wasm.yml
|
||||||
runs-on: runs-on=${{ github.run_id }}/family=i7ie.2xlarge/image=ubuntu22-full-x64
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: npm install
|
|
||||||
|
|
||||||
- name: Use correct Rust toolchain
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
[ -e rust-toolchain.toml ] || cp rust/rust-toolchain.toml ./
|
|
||||||
|
|
||||||
- name: Install rust
|
|
||||||
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
with:
|
|
||||||
cache: false # Configured below.
|
|
||||||
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
|
||||||
with:
|
|
||||||
tool: wasm-pack
|
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
with:
|
|
||||||
workspaces: './rust'
|
|
||||||
|
|
||||||
- name: Build Wasm
|
|
||||||
shell: bash
|
|
||||||
run: npm run build:wasm
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: prepared-wasm
|
|
||||||
path: |
|
|
||||||
rust/kcl-wasm-lib/pkg/kcl_wasm_lib*
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: prepared-ts-rs-bindings
|
|
||||||
path: |
|
|
||||||
rust/kcl-lib/bindings/*
|
|
||||||
|
|
||||||
npm-tsc:
|
npm-tsc:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -173,116 +127,3 @@ jobs:
|
|||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Run codespell
|
- name: Run codespell
|
||||||
uses: crate-ci/typos@v1.32.0
|
uses: crate-ci/typos@v1.32.0
|
||||||
|
|
||||||
npm-unit-test-kcl-samples:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: npm-build-wasm
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- run: npm install
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
|
||||||
with:
|
|
||||||
tool: wasm-pack
|
|
||||||
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
|
||||||
run: |
|
|
||||||
ls -R prepared-wasm
|
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
|
||||||
mkdir rust/kcl-wasm-lib/pkg
|
|
||||||
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
|
||||||
|
|
||||||
- name: Copy prepared ts-rs bindings
|
|
||||||
run: |
|
|
||||||
ls -R prepared-ts-rs-bindings
|
|
||||||
mkdir rust/kcl-lib/bindings
|
|
||||||
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
|
||||||
|
|
||||||
- run: npm run simpleserver:bg
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
|
|
||||||
- name: Install Chromium Browser
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: npm run playwright install chromium --with-deps
|
|
||||||
|
|
||||||
- name: run unit tests for kcl samples
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: npm run test:unit:kcl-samples
|
|
||||||
env:
|
|
||||||
VITE_KC_DEV_TOKEN: ${{ secrets.KITTYCAD_API_TOKEN_DEV }}
|
|
||||||
|
|
||||||
npm-unit-test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: npm-build-wasm
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
cache: 'npm'
|
|
||||||
|
|
||||||
- run: npm install
|
|
||||||
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
|
||||||
with:
|
|
||||||
tool: wasm-pack
|
|
||||||
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
|
|
||||||
- name: Copy prepared wasm
|
|
||||||
run: |
|
|
||||||
ls -R prepared-wasm
|
|
||||||
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
|
||||||
mkdir rust/kcl-wasm-lib/pkg
|
|
||||||
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
|
||||||
|
|
||||||
- name: Copy prepared ts-rs bindings
|
|
||||||
run: |
|
|
||||||
ls -R prepared-ts-rs-bindings
|
|
||||||
mkdir rust/kcl-lib/bindings
|
|
||||||
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
|
||||||
|
|
||||||
- run: npm run simpleserver:bg
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
|
|
||||||
- name: Install Chromium Browser
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: npm run playwright install chromium --with-deps
|
|
||||||
|
|
||||||
- name: Run unit tests
|
|
||||||
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
|
||||||
run: xvfb-run -a npm run test:unit
|
|
||||||
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 }}
|
|
||||||
|
39
.github/workflows/tag-nightly.yml
vendored
@ -1,39 +0,0 @@
|
|||||||
name: tag-nightly
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
on:
|
|
||||||
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)
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
tag-nightly:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/create-github-app-token@v1
|
|
||||||
id: app-token
|
|
||||||
with:
|
|
||||||
app-id: ${{ secrets.MODELING_APP_GH_APP_ID }}
|
|
||||||
private-key: ${{ secrets.MODELING_APP_GH_APP_PRIVATE_KEY }}
|
|
||||||
owner: ${{ github.repository_owner }}
|
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ steps.app-token.outputs.token }}
|
|
||||||
|
|
||||||
- uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
|
|
||||||
- run: npm install
|
|
||||||
|
|
||||||
- name: Push tag
|
|
||||||
run: |
|
|
||||||
VERSION_NO_V=$(date +'%-y.%-m.%-d')
|
|
||||||
TAG="nightly-v$VERSION_NO_V"
|
|
||||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
git config --local user.name "github-actions[bot]"
|
|
||||||
git tag $TAG
|
|
||||||
git push origin tag $TAG
|
|
124
.github/workflows/unit-tests.yml
vendored
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
name: Unit Tests
|
||||||
|
|
||||||
|
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:
|
||||||
|
npm-build-wasm:
|
||||||
|
uses: ./.github/workflows/build-wasm.yml
|
||||||
|
|
||||||
|
npm-test-unit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: npm-build-wasm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- run: npm install
|
||||||
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
|
with:
|
||||||
|
tool: wasm-pack
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- name: Copy prepared wasm
|
||||||
|
run: |
|
||||||
|
ls -R prepared-wasm
|
||||||
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
|
mkdir rust/kcl-wasm-lib/pkg
|
||||||
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
|
- name: Copy prepared ts-rs bindings
|
||||||
|
run: |
|
||||||
|
ls -R prepared-ts-rs-bindings
|
||||||
|
mkdir rust/kcl-lib/bindings
|
||||||
|
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
||||||
|
|
||||||
|
- run: npm run simpleserver:bg
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
|
||||||
|
- name: Install Chromium Browser
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
run: npm run playwright install chromium --with-deps
|
||||||
|
|
||||||
|
- name: Run unit tests
|
||||||
|
if: ${{ github.event_name != 'release' && github.event_name != 'schedule' }}
|
||||||
|
run: xvfb-run -a npm run test:unit
|
||||||
|
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 }}
|
||||||
|
|
||||||
|
npm-test-unit-components:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: npm-build-wasm
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- run: npm install
|
||||||
|
- uses: taiki-e/install-action@d4635f2de61c8b8104d59cd4aede2060638378cc
|
||||||
|
with:
|
||||||
|
tool: wasm-pack
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
|
||||||
|
- name: Copy prepared wasm
|
||||||
|
run: |
|
||||||
|
ls -R prepared-wasm
|
||||||
|
cp prepared-wasm/kcl_wasm_lib_bg.wasm public
|
||||||
|
mkdir rust/kcl-wasm-lib/pkg
|
||||||
|
cp prepared-wasm/kcl_wasm_lib* rust/kcl-wasm-lib/pkg
|
||||||
|
|
||||||
|
- name: Copy prepared ts-rs bindings
|
||||||
|
run: |
|
||||||
|
ls -R prepared-ts-rs-bindings
|
||||||
|
mkdir rust/kcl-lib/bindings
|
||||||
|
cp -r prepared-ts-rs-bindings/* rust/kcl-lib/bindings/
|
||||||
|
|
||||||
|
- name: Run component tests
|
||||||
|
run: npm run test:unit:components
|
2
.gitignore
vendored
@ -58,6 +58,8 @@ trace.zip
|
|||||||
/public/kcl-samples/.github
|
/public/kcl-samples/.github
|
||||||
/public/kcl-samples/screenshots/main.kcl
|
/public/kcl-samples/screenshots/main.kcl
|
||||||
/public/kcl-samples/step/main.kcl
|
/public/kcl-samples/step/main.kcl
|
||||||
|
/public/kcl-samples/internal
|
||||||
|
/rust/kcl-lib/tests/kcl_samples/internal
|
||||||
/test-results/
|
/test-results/
|
||||||
/playwright-report/
|
/playwright-report/
|
||||||
/blob-report/
|
/blob-report/
|
||||||
|
@ -130,7 +130,7 @@ git tag $VERSION
|
|||||||
git push origin --tags
|
git push origin --tags
|
||||||
```
|
```
|
||||||
|
|
||||||
This will trigger the `build-apps` workflow, set the version, build & sign the apps, and generate release files as well as updater-test artifacts.
|
This will trigger the `build-apps` workflow, set the version, build & sign the apps, and generate release files.
|
||||||
|
|
||||||
The workflow should be listed right away [in this list](https://github.com/KittyCAD/modeling-app/actions/workflows/build-apps.yml?query=event%3Apush)).
|
The workflow should be listed right away [in this list](https://github.com/KittyCAD/modeling-app/actions/workflows/build-apps.yml?query=event%3Apush)).
|
||||||
|
|
||||||
@ -142,13 +142,10 @@ The release builds can be found under the `out-{arch}-{platform}` zip files, at
|
|||||||
|
|
||||||
Manually test against this [list](https://github.com/KittyCAD/modeling-app/issues/3588) across Windows, MacOS, Linux and posting results as comments in the issue.
|
Manually test against this [list](https://github.com/KittyCAD/modeling-app/issues/3588) across Windows, MacOS, Linux and posting results as comments in the issue.
|
||||||
|
|
||||||
##### Updater-test builds
|
A prompt should show up asking for a downgrade to the last release version. Running through that at the end of testing
|
||||||
|
and making sure the current release candidate has the ability to be updated to what electron-updater points to is critical,
|
||||||
The other `build-apps` output in the release `build-apps` workflow (triggered by 2.) is `updater-test-{arch}-{platform}`. It's a semi-automated process: for macOS, Windows, and Linux, download the corresponding updater-test artifact file, install the app, run it, expect an updater prompt to a dummy v0.255.255, install it and check that the app comes back at that version.
|
but what is actually being downloaded and installed isn't.
|
||||||
|
If the prompt doesn't show up, start the app in command line to grab the electron-updater logs. This is likely an issue with the current build that needs addressing.
|
||||||
The only difference with these builds is that they point to a different update location on the release bucket, with this dummy v0.255.255 always available. This helps ensuring that the version we release will be able to update to the next one available.
|
|
||||||
|
|
||||||
If the prompt doesn't show up, start the app in command line to grab the electron-updater logs. This is likely an issue with the current build that needs addressing (or the updater-test location in the storage bucket).
|
|
||||||
|
|
||||||
```
|
```
|
||||||
# Windows (PowerShell)
|
# Windows (PowerShell)
|
||||||
|
9
Makefile
@ -23,6 +23,7 @@ endif
|
|||||||
install: node_modules/.package-lock.json $(CARGO) $(WASM_PACK) ## Install dependencies
|
install: node_modules/.package-lock.json $(CARGO) $(WASM_PACK) ## Install dependencies
|
||||||
|
|
||||||
node_modules/.package-lock.json: package.json package-lock.json
|
node_modules/.package-lock.json: package.json package-lock.json
|
||||||
|
npm prune
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
$(CARGO):
|
$(CARGO):
|
||||||
@ -43,15 +44,15 @@ endif
|
|||||||
# BUILD
|
# BUILD
|
||||||
|
|
||||||
CARGO_SOURCES := rust/.cargo/config.toml $(wildcard rust/Cargo.*) $(wildcard rust/**/Cargo.*)
|
CARGO_SOURCES := rust/.cargo/config.toml $(wildcard rust/Cargo.*) $(wildcard rust/**/Cargo.*)
|
||||||
|
KCL_SOURCES := $(wildcard public/kcl-samples/**/*.kcl)
|
||||||
RUST_SOURCES := $(wildcard rust/**/*.rs)
|
RUST_SOURCES := $(wildcard rust/**/*.rs)
|
||||||
|
|
||||||
REACT_SOURCES := $(wildcard src/*.tsx) $(wildcard src/**/*.tsx)
|
REACT_SOURCES := $(wildcard src/*.tsx) $(wildcard src/**/*.tsx)
|
||||||
TYPESCRIPT_SOURCES := tsconfig.* $(wildcard src/*.ts) $(wildcard src/**/*.ts)
|
TYPESCRIPT_SOURCES := tsconfig.* $(wildcard src/*.ts) $(wildcard src/**/*.ts)
|
||||||
VITE_SOURCES := $(wildcard vite.*) $(wildcard vite/**/*.tsx)
|
VITE_SOURCES := $(wildcard vite.*) $(wildcard vite/**/*.tsx)
|
||||||
|
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: install public/kcl_wasm_lib_bg.wasm .vite/build/main.js
|
build: install public/kcl_wasm_lib_bg.wasm public/kcl-samples/manifest.json .vite/build/main.js
|
||||||
|
|
||||||
public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES) $(RUST_SOURCES)
|
public/kcl_wasm_lib_bg.wasm: $(CARGO_SOURCES) $(RUST_SOURCES)
|
||||||
ifdef WINDOWS
|
ifdef WINDOWS
|
||||||
@ -60,6 +61,9 @@ else
|
|||||||
npm run build:wasm:dev
|
npm run build:wasm:dev
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
public/kcl-samples/manifest.json: $(KCL_SOURCES)
|
||||||
|
cd rust/kcl-lib && EXPECTORATE=overwrite cargo test generate_manifest
|
||||||
|
|
||||||
.vite/build/main.js: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
|
.vite/build/main.js: $(REACT_SOURCES) $(TYPESCRIPT_SOURCES) $(VITE_SOURCES)
|
||||||
npm run tronb:vite:dev
|
npm run tronb:vite:dev
|
||||||
|
|
||||||
@ -107,6 +111,7 @@ test: test-unit test-e2e
|
|||||||
.PHONY: test-unit
|
.PHONY: test-unit
|
||||||
test-unit: install ## Run the unit tests
|
test-unit: install ## Run the unit tests
|
||||||
npm run test:rust
|
npm run test:rust
|
||||||
|
npm run test:unit:components
|
||||||
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
|
@ curl -fs localhost:3000 >/dev/null || ( echo "Error: localhost:3000 not available, 'make run-web' first" && exit 1 )
|
||||||
npm run test:unit
|
npm run test:unit
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ The 3D view in Design Studio is just a video stream from our hosted geometry eng
|
|||||||
- WebSockets (via [KittyCAD TS client](https://github.com/KittyCAD/kittycad.ts))
|
- WebSockets (via [KittyCAD TS client](https://github.com/KittyCAD/kittycad.ts))
|
||||||
- Code Editor
|
- Code Editor
|
||||||
- [CodeMirror](https://codemirror.net/)
|
- [CodeMirror](https://codemirror.net/)
|
||||||
- Custom WASM LSP Server
|
- [Custom WASM LSP Server](https://github.com/KittyCAD/modeling-app/tree/main/rust/kcl-lib/src/lsp/kcl)
|
||||||
- Modeling
|
- Modeling
|
||||||
- [KittyCAD TypeScript client](https://github.com/KittyCAD/kittycad.ts)
|
- [KittyCAD TypeScript client](https://github.com/KittyCAD/kittycad.ts)
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ THRE = "THRE" # Weird bug that wrongly detects THREEjs as a typo
|
|||||||
nwo = "nwo" # don't know what this is about tbh
|
nwo = "nwo" # don't know what this is about tbh
|
||||||
"ot" = "ot" # some abbreviation, idk what
|
"ot" = "ot" # some abbreviation, idk what
|
||||||
"oe" = "oe" # some abbreviation, idk what
|
"oe" = "oe" # some abbreviation, idk what
|
||||||
|
"colinear" = "colinear" # some engine shit, kidding
|
||||||
|
|
||||||
[default]
|
[default]
|
||||||
extend-ignore-identifiers-re = [
|
extend-ignore-identifiers-re = [
|
||||||
|
32
docs/kcl-lang/arrays.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
title: "Arrays and ranges"
|
||||||
|
excerpt: "Documentation of the KCL language for the Zoo Design Studio."
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
Arrays are sequences of values.
|
||||||
|
|
||||||
|
Arrays can be written out as *array literals* using a sequence of expressions surrounded by square brackets, e.g., `['hello', 'world']` is an array of strings, `[x, x + 1, x + 2]` is an array of numbers (assuming `x` is a number), `[]` is an empty array, and `['hello', 42, true]` is a mixed array.
|
||||||
|
|
||||||
|
A value in an array can be accessed by indexing using square brackets where the index is a number, for example, `arr[0]`, `arr[42]`, `arr[i]` (where `arr` is an array and `i` is a (whole) number).
|
||||||
|
|
||||||
|
There are some useful functions for working with arrays in the standard library, see [std::array](/docs/kcl-std/modules/std-array) for details.
|
||||||
|
|
||||||
|
## Array types
|
||||||
|
|
||||||
|
Arrays have their own types: `[T]` where `T` is the type of the elements of the array, for example, `[string]` means an array of `string`s and `[any]` means an array of any values.
|
||||||
|
|
||||||
|
Array types can also include length information: `[T; n]` denotes an array of length `n` (where `n` is a number literal) and `[T; 1+]` denotes an array whose length is at least one (i.e., a non-empty array). E.g., `[string; 1+]` and `[number(mm); 3]` are valid array types.
|
||||||
|
|
||||||
|
## Ranges
|
||||||
|
|
||||||
|
Ranges are a succinct way to create an array of sequential numbers. The syntax is `[start .. end]` where `start` and `end` evaluate to whole numbers (integers). Ranges are inclusive of the start and end. The end must be greater than the start. Examples:
|
||||||
|
|
||||||
|
```kcl,norun
|
||||||
|
[0..3] // [0, 1, 2, 3]
|
||||||
|
[3..10] // [3, 4, 5, 6, 7, 8, 9, 10]
|
||||||
|
x = 2
|
||||||
|
[x..x+1] // [2, 3]
|
||||||
|
```
|
||||||
|
|
||||||
|
The units of the start and end numbers must be the same and the result inherits those units.
|
99
docs/kcl-lang/foreign-imports.md
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
---
|
||||||
|
title: "Importing geometry from other CAD systems"
|
||||||
|
excerpt: "Documentation of the KCL language for the Zoo Design Studio."
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
`import` can also be used to import files from other CAD systems. The format of the statement is the
|
||||||
|
same as for KCL files. You can only import the whole file, not items from it. E.g.,
|
||||||
|
|
||||||
|
```norun
|
||||||
|
import "tests/inputs/cube.obj"
|
||||||
|
|
||||||
|
// Use `cube` just like a KCL object.
|
||||||
|
```
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
import "tests/inputs/cube.sldprt" as cube
|
||||||
|
|
||||||
|
// Use `cube` just like a KCL object.
|
||||||
|
```
|
||||||
|
|
||||||
|
For formats lacking unit data (such as STL, OBJ, or PLY files), the default
|
||||||
|
unit of measurement is millimeters. Alternatively you may specify the unit
|
||||||
|
by using an attribute. Likewise, you can also specify a coordinate system. E.g.,
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
@(lengthUnit = ft, coords = opengl)
|
||||||
|
import "tests/inputs/cube.obj"
|
||||||
|
```
|
||||||
|
|
||||||
|
When importing a GLTF file, the bin file will be imported as well.
|
||||||
|
|
||||||
|
Import paths are relative to the current project directory. Imports currently only work when
|
||||||
|
using the native Design Studio, not in the browser.
|
||||||
|
|
||||||
|
### Supported values
|
||||||
|
|
||||||
|
File formats: `fbx`, `gltf`/`glb`, `obj`+, `ply`+, `sldprt`, `step`/`stp`, `stl`+. (Those marked with a
|
||||||
|
'+' support customising the length unit and coordinate system).
|
||||||
|
|
||||||
|
Length units: `mm` (the default), `cm`, `m`, `inch`, `ft`, `yd`.
|
||||||
|
|
||||||
|
Coordinate systems:
|
||||||
|
|
||||||
|
- `zoo` (the default), forward: -Y, up: +Z, handedness: right
|
||||||
|
- `opengl`, forward: +Z, up: +Y, handedness: right
|
||||||
|
- `vulkan`, forward: +Z, up: -Y, handedness: left
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Performance deep‑dive for foreign‑file imports
|
||||||
|
|
||||||
|
Parallelized foreign‑file imports now let you overlap file reads, initialization,
|
||||||
|
and rendering. To maximize throughput, you need to understand the three distinct
|
||||||
|
stages—reading, initializing (background render start), and invocation (blocking)
|
||||||
|
—and structure your code to defer blocking operations until the end.
|
||||||
|
|
||||||
|
### Foreign import execution stages
|
||||||
|
|
||||||
|
1. **Import (Read / Initialization) Stage**
|
||||||
|
```kcl
|
||||||
|
import "tests/inputs/cube.step" as cube
|
||||||
|
```
|
||||||
|
- Reads the file from disk and makes its API available.
|
||||||
|
- Starts engine rendering but **does not block** your script.
|
||||||
|
- This kick‑starts the render pipeline while you keep executing other code.
|
||||||
|
|
||||||
|
2. **Invocation (Blocking) Stage**
|
||||||
|
```kcl
|
||||||
|
import "tests/inputs/cube.step" as cube
|
||||||
|
|
||||||
|
cube
|
||||||
|
|> translate(z=10) // ← blocks here only
|
||||||
|
```
|
||||||
|
- Any method call (e.g., `translate`, `scale`, `rotate`) waits for the background render to finish before applying transformations.
|
||||||
|
|
||||||
|
### Best practices
|
||||||
|
|
||||||
|
#### 1. Defer blocking calls
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
import "tests/inputs/cube.step" as cube // 1) Read / Background render starts
|
||||||
|
|
||||||
|
|
||||||
|
// --- perform other operations and calculations here ---
|
||||||
|
|
||||||
|
|
||||||
|
cube
|
||||||
|
|> translate(z=10) // 2) Blocks only here
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Split heavy work into separate modules
|
||||||
|
|
||||||
|
Place computationally expensive or IO‑heavy work into its own module so it can render in parallel while `main.kcl` continues.
|
||||||
|
|
||||||
|
#### Future improvements
|
||||||
|
|
||||||
|
Upcoming releases will auto‑analyse dependencies and only block when truly necessary. Until then, explicit deferral will give you the best performance.
|
||||||
|
|
@ -5,7 +5,7 @@ layout: manual
|
|||||||
---
|
---
|
||||||
|
|
||||||
This is a reference for KCL. If you are learning KCL, you may prefer the [guide]() which explains
|
This is a reference for KCL. If you are learning KCL, you may prefer the [guide]() which explains
|
||||||
things in a more tutorial fashion.
|
things in a more tutorial fashion. See also our documentation of the [standard library](/docs/kcl-std).
|
||||||
|
|
||||||
## Topics
|
## Topics
|
||||||
|
|
||||||
@ -14,7 +14,9 @@ things in a more tutorial fashion.
|
|||||||
* [Values and types](/docs/kcl-lang/types)
|
* [Values and types](/docs/kcl-lang/types)
|
||||||
* [Numeric types and units](/docs/kcl-lang/numeric)
|
* [Numeric types and units](/docs/kcl-lang/numeric)
|
||||||
* [Functions](/docs/kcl-lang/functions)
|
* [Functions](/docs/kcl-lang/functions)
|
||||||
* [Projects, modules, and imports](/docs/kcl-lang/modules)
|
* [Arrays and ranges](/docs/kcl-lang/arrays)
|
||||||
|
* [Projects and modules](/docs/kcl-lang/modules)
|
||||||
* [Attributes](/docs/kcl-lang/attributes)
|
* [Attributes](/docs/kcl-lang/attributes)
|
||||||
|
* [Importing geometry from other CAD systems](/docs/kcl-lang/foreign-imports)
|
||||||
* [Settings](/docs/kcl-lang/settings)
|
* [Settings](/docs/kcl-lang/settings)
|
||||||
* [Known Issues](/docs/kcl-lang/known-issues)
|
* [Known Issues](/docs/kcl-lang/known-issues)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: "Modules"
|
title: "Projects and modules"
|
||||||
excerpt: "Documentation of the KCL language for the Zoo Design Studio."
|
excerpt: "Documentation of the KCL language for the Zoo Design Studio."
|
||||||
layout: manual
|
layout: manual
|
||||||
---
|
---
|
||||||
@ -264,102 +264,3 @@ cube
|
|||||||
clone(cube)
|
clone(cube)
|
||||||
|> translate(x=20)
|
|> translate(x=20)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Importing files from other CAD systems
|
|
||||||
|
|
||||||
`import` can also be used to import files from other CAD systems. The format of the statement is the
|
|
||||||
same as for KCL files. You can only import the whole file, not items from it. E.g.,
|
|
||||||
|
|
||||||
```norun
|
|
||||||
import "tests/inputs/cube.obj"
|
|
||||||
|
|
||||||
// Use `cube` just like a KCL object.
|
|
||||||
```
|
|
||||||
|
|
||||||
```kcl
|
|
||||||
import "tests/inputs/cube.sldprt" as cube
|
|
||||||
|
|
||||||
// Use `cube` just like a KCL object.
|
|
||||||
```
|
|
||||||
|
|
||||||
For formats lacking unit data (such as STL, OBJ, or PLY files), the default
|
|
||||||
unit of measurement is millimeters. Alternatively you may specify the unit
|
|
||||||
by using an attribute. Likewise, you can also specify a coordinate system. E.g.,
|
|
||||||
|
|
||||||
```kcl
|
|
||||||
@(lengthUnit = ft, coords = opengl)
|
|
||||||
import "tests/inputs/cube.obj"
|
|
||||||
```
|
|
||||||
|
|
||||||
When importing a GLTF file, the bin file will be imported as well.
|
|
||||||
|
|
||||||
Import paths are relative to the current project directory. Imports currently only work when
|
|
||||||
using the native Design Studio, not in the browser.
|
|
||||||
|
|
||||||
### Supported values
|
|
||||||
|
|
||||||
File formats: `fbx`, `gltf`/`glb`, `obj`+, `ply`+, `sldprt`, `step`/`stp`, `stl`+. (Those marked with a
|
|
||||||
'+' support customising the length unit and coordinate system).
|
|
||||||
|
|
||||||
Length units: `mm` (the default), `cm`, `m`, `inch`, `ft`, `yd`.
|
|
||||||
|
|
||||||
Coordinate systems:
|
|
||||||
|
|
||||||
- `zoo` (the default), forward: -Y, up: +Z, handedness: right
|
|
||||||
- `opengl`, forward: +Z, up: +Y, handedness: right
|
|
||||||
- `vulkan`, forward: +Z, up: -Y, handedness: left
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Performance deep‑dive for foreign‑file imports
|
|
||||||
|
|
||||||
Parallelized foreign‑file imports now let you overlap file reads, initialization,
|
|
||||||
and rendering. To maximize throughput, you need to understand the three distinct
|
|
||||||
stages—reading, initializing (background render start), and invocation (blocking)
|
|
||||||
—and structure your code to defer blocking operations until the end.
|
|
||||||
|
|
||||||
### Foreign import execution stages
|
|
||||||
|
|
||||||
1. **Import (Read / Initialization) Stage**
|
|
||||||
```kcl
|
|
||||||
import "tests/inputs/cube.step" as cube
|
|
||||||
```
|
|
||||||
- Reads the file from disk and makes its API available.
|
|
||||||
- Starts engine rendering but **does not block** your script.
|
|
||||||
- This kick‑starts the render pipeline while you keep executing other code.
|
|
||||||
|
|
||||||
2. **Invocation (Blocking) Stage**
|
|
||||||
```kcl
|
|
||||||
import "tests/inputs/cube.step" as cube
|
|
||||||
|
|
||||||
cube
|
|
||||||
|> translate(z=10) // ← blocks here only
|
|
||||||
```
|
|
||||||
- Any method call (e.g., `translate`, `scale`, `rotate`) waits for the background render to finish before applying transformations.
|
|
||||||
|
|
||||||
### Best practices
|
|
||||||
|
|
||||||
#### 1. Defer blocking calls
|
|
||||||
|
|
||||||
```kcl
|
|
||||||
import "tests/inputs/cube.step" as cube // 1) Read / Background render starts
|
|
||||||
|
|
||||||
|
|
||||||
// --- perform other operations and calculations here ---
|
|
||||||
|
|
||||||
|
|
||||||
cube
|
|
||||||
|> translate(z=10) // 2) Blocks only here
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. Split heavy work into separate modules
|
|
||||||
|
|
||||||
Place computationally expensive or IO‑heavy work into its own module so it can render in parallel while `main.kcl` continues.
|
|
||||||
|
|
||||||
#### Future improvements
|
|
||||||
|
|
||||||
Upcoming releases will auto‑analyse dependencies and only block when truly necessary. Until then, explicit deferral will give you the best performance.
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ Any of the suffixes described above can be used meaning that values with that ty
|
|||||||
|
|
||||||
You can also use `number(Length)`, `number(Angle)`, or `number(Count)`. These types mean a number with any length, angle, or unitless (count) units, respectively (note that `number(_)` and `number(Count)` are equivalent since there is only one kind of unitless-ness).
|
You can also use `number(Length)`, `number(Angle)`, or `number(Count)`. These types mean a number with any length, angle, or unitless (count) units, respectively (note that `number(_)` and `number(Count)` are equivalent since there is only one kind of unitless-ness).
|
||||||
|
|
||||||
|
Using just `number` means accepting any kind of number, even where the units are unknown by KCL.
|
||||||
|
|
||||||
|
|
||||||
## Function calls
|
## Function calls
|
||||||
|
|
||||||
|
@ -19,18 +19,6 @@ myBool = false
|
|||||||
|
|
||||||
Currently you cannot redeclare a constant.
|
Currently you cannot redeclare a constant.
|
||||||
|
|
||||||
## Arrays
|
|
||||||
|
|
||||||
An array is defined with `[]` braces. What is inside the brackets can
|
|
||||||
be of any type. For example, the following is completely valid:
|
|
||||||
|
|
||||||
```
|
|
||||||
myArray = ["thing", 2, false]
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to get a value from an array you can use the index like so:
|
|
||||||
`myArray[0]`.
|
|
||||||
|
|
||||||
|
|
||||||
## Objects
|
## Objects
|
||||||
|
|
||||||
@ -40,8 +28,8 @@ An object is defined with `{}` braces. Here is an example object:
|
|||||||
myObj = { a = 0, b = "thing" }
|
myObj = { a = 0, b = "thing" }
|
||||||
```
|
```
|
||||||
|
|
||||||
We support two different ways of getting properties from objects, you can call
|
To get the property of an object, you can call `myObj.a`, which in the above
|
||||||
`myObj.a` or `myObj["a"]` both work.
|
example returns 0.
|
||||||
|
|
||||||
## `ImportedGeometry`
|
## `ImportedGeometry`
|
||||||
|
|
||||||
|
@ -11,7 +11,13 @@ The value of `pi`, Archimedes’ constant (π).
|
|||||||
PI: number(_?) = 3.14159265358979323846264338327950288_?
|
PI: number(_?) = 3.14159265358979323846264338327950288_?
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`PI` is a number and is technically a ratio, so you might expect it to have type `number(_)`.
|
||||||
|
However, `PI` is nearly always used for converting between different units - usually degrees to or
|
||||||
|
from radians. Therefore, `PI` is treated a bit specially by KCL and always has unknown units. This
|
||||||
|
means that if you use `PI`, you will need to give KCL some extra information about the units of numbers.
|
||||||
|
Usually you should use type ascription on the result of calculations, e.g., `(2 * PI): number(rad)`.
|
||||||
|
You might prefer to use `units::toRadians` or `units::toDegrees` to convert between angles with
|
||||||
|
different units.
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
|
||||||
|
16
docs/kcl-std/consts/std-sweep-SKETCH_PLANE.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "sweep::SKETCH_PLANE"
|
||||||
|
subtitle: "Constant in std::sweep"
|
||||||
|
excerpt: "Local/relative to a position centered within the plane being sketched on"
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
Local/relative to a position centered within the plane being sketched on
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
sweep::SKETCH_PLANE: string = 'sketchPlane'
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
16
docs/kcl-std/consts/std-sweep-TRAJECTORY.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "sweep::TRAJECTORY"
|
||||||
|
subtitle: "Constant in std::sweep"
|
||||||
|
excerpt: "Local/relative to the trajectory curve"
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
Local/relative to the trajectory curve
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
sweep::TRAJECTORY: string = 'trajectoryCurve'
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ You can provide more than one sketch to extrude, and they will all be extruded i
|
|||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `sketches` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch or sketches should be extruded | Yes |
|
| `sketches` | [`[Sketch]`](/docs/kcl-std/types/std-types-Sketch) | Which sketch or sketches should be extruded | Yes |
|
||||||
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | How far to extrude the given sketches | Yes |
|
| `length` | [`number`](/docs/kcl-std/types/std-types-number) | How far to extrude the given sketches | Yes |
|
||||||
| `symmetric` | [`bool`](/docs/kcl-std/types/std-types-bool) | If true, the extrusion will happen symmetrically around the sketch. Otherwise, the | No |
|
| `symmetric` | [`bool`](/docs/kcl-std/types/std-types-bool) | If true, the extrusion will happen symmetrically around the sketch. Otherwise, the extrusion will happen on only one side of the sketch. | No |
|
||||||
| `bidirectionalLength` | [`number`](/docs/kcl-std/types/std-types-number) | If specified, will also extrude in the opposite direction to 'distance' to the specified distance. If 'symmetric' is true, this value is ignored. | No |
|
| `bidirectionalLength` | [`number`](/docs/kcl-std/types/std-types-number) | If specified, will also extrude in the opposite direction to 'distance' to the specified distance. If 'symmetric' is true, this value is ignored. | No |
|
||||||
| `tagStart` | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | A named tag for the face at the start of the extrusion, i.e. the original sketch | No |
|
| `tagStart` | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | A named tag for the face at the start of the extrusion, i.e. the original sketch | No |
|
||||||
| `tagEnd` | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch | No |
|
| `tagEnd` | [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator) | A named tag for the face at the end of the extrusion, i.e. the new face created by extruding the original sketch | No |
|
||||||
|
38
docs/kcl-std/functions/std-math-legAngX.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
title: "legAngX"
|
||||||
|
subtitle: "Function in std::math"
|
||||||
|
excerpt: "Compute the angle of the given leg for x."
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
Compute the angle of the given leg for x.
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
legAngX(
|
||||||
|
hypotenuse: number(Length),
|
||||||
|
leg: number(Length),
|
||||||
|
): number(deg)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
| Name | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `hypotenuse` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse. | Yes |
|
||||||
|
| `leg` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side). | Yes |
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
|
||||||
|
[`number(deg)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
legAngX(hypotenuse = 5, leg = 3)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
38
docs/kcl-std/functions/std-math-legAngY.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
title: "legAngY"
|
||||||
|
subtitle: "Function in std::math"
|
||||||
|
excerpt: "Compute the angle of the given leg for y."
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
Compute the angle of the given leg for y.
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
legAngY(
|
||||||
|
hypotenuse: number(Length),
|
||||||
|
leg: number(Length),
|
||||||
|
): number(deg)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
| Name | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `hypotenuse` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse. | Yes |
|
||||||
|
| `leg` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side). | Yes |
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
|
||||||
|
[`number(deg)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
legAngY(hypotenuse = 5, leg = 3)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
38
docs/kcl-std/functions/std-math-legLen.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
title: "legLen"
|
||||||
|
subtitle: "Function in std::math"
|
||||||
|
excerpt: "Compute the length of the given leg."
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
Compute the length of the given leg.
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
legLen(
|
||||||
|
hypotenuse: number(Length),
|
||||||
|
leg: number(Length),
|
||||||
|
): number(deg)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
| Name | Type | Description | Required |
|
||||||
|
|----------|------|-------------|----------|
|
||||||
|
| `hypotenuse` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse. | Yes |
|
||||||
|
| `leg` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side). | Yes |
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
|
||||||
|
[`number(deg)`](/docs/kcl-std/types/std-types-number) - A number.
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```kcl
|
||||||
|
legLen(hypotenuse = 5, leg = 3)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -8,7 +8,7 @@ layout: manual
|
|||||||
Convert a number to centimeters from its current units.
|
Convert a number to centimeters from its current units.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
units::toCentimeters(@num: number(cm)): number(cm)
|
units::toCentimeters(@num: number(Length)): number(cm)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ units::toCentimeters(@num: number(cm)): number(cm)
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `num` | [`number(cm)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
| `num` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ layout: manual
|
|||||||
Converts a number to degrees from its current units.
|
Converts a number to degrees from its current units.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
units::toDegrees(@num: number(deg)): number(deg)
|
units::toDegrees(@num: number(Angle)): number(deg)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ units::toDegrees(@num: number(deg)): number(deg)
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `num` | [`number(deg)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
| `num` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ layout: manual
|
|||||||
Convert a number to feet from its current units.
|
Convert a number to feet from its current units.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
units::toFeet(@num: number(ft)): number(ft)
|
units::toFeet(@num: number(Length)): number(ft)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ units::toFeet(@num: number(ft)): number(ft)
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `num` | [`number(ft)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
| `num` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ layout: manual
|
|||||||
Convert a number to inches from its current units.
|
Convert a number to inches from its current units.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
units::toInches(@num: number(in)): number(in)
|
units::toInches(@num: number(Length)): number(in)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ units::toInches(@num: number(in)): number(in)
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `num` | [`number(in)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
| `num` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ layout: manual
|
|||||||
Convert a number to meters from its current units.
|
Convert a number to meters from its current units.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
units::toMeters(@num: number(m)): number(m)
|
units::toMeters(@num: number(Length)): number(m)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ units::toMeters(@num: number(m)): number(m)
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `num` | [`number(m)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
| `num` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ layout: manual
|
|||||||
Convert a number to millimeters from its current units.
|
Convert a number to millimeters from its current units.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
units::toMillimeters(@num: number(mm)): number(mm)
|
units::toMillimeters(@num: number(Length)): number(mm)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ units::toMillimeters(@num: number(mm)): number(mm)
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `num` | [`number(mm)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
| `num` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ layout: manual
|
|||||||
Converts a number to radians from its current units.
|
Converts a number to radians from its current units.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
units::toRadians(@num: number(rad)): number(rad)
|
units::toRadians(@num: number(Angle)): number(rad)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ units::toRadians(@num: number(rad)): number(rad)
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `num` | [`number(rad)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
| `num` | [`number(Angle)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ layout: manual
|
|||||||
Converts a number to yards from its current units.
|
Converts a number to yards from its current units.
|
||||||
|
|
||||||
```kcl
|
```kcl
|
||||||
units::toYards(@num: number(yd)): number(yd)
|
units::toYards(@num: number(Length)): number(yd)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +17,7 @@ units::toYards(@num: number(yd)): number(yd)
|
|||||||
|
|
||||||
| Name | Type | Description | Required |
|
| Name | Type | Description | Required |
|
||||||
|----------|------|-------------|----------|
|
|----------|------|-------------|----------|
|
||||||
| `num` | [`number(yd)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
| `num` | [`number(Length)`](/docs/kcl-std/types/std-types-number) | A number. | Yes |
|
||||||
|
|
||||||
### Returns
|
### Returns
|
||||||
|
|
||||||
|
@ -12,15 +12,15 @@ layout: manual
|
|||||||
* [`appearance`](/docs/kcl-std/appearance)
|
* [`appearance`](/docs/kcl-std/appearance)
|
||||||
* [`assert`](/docs/kcl-std/assert)
|
* [`assert`](/docs/kcl-std/assert)
|
||||||
* [`assertIs`](/docs/kcl-std/assertIs)
|
* [`assertIs`](/docs/kcl-std/assertIs)
|
||||||
* [`clone`](/docs/kcl-std/clone)
|
* [`clone`](/docs/kcl-std/functions/std-clone)
|
||||||
* [`helix`](/docs/kcl-std/functions/std-helix)
|
* [`helix`](/docs/kcl-std/functions/std-helix)
|
||||||
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
||||||
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
||||||
* [**std::array**](/docs/kcl-std/modules/std-array)
|
* [**std::array**](/docs/kcl-std/modules/std-array)
|
||||||
* [`map`](/docs/kcl-std/map)
|
* [`map`](/docs/kcl-std/functions/std-array-map)
|
||||||
* [`pop`](/docs/kcl-std/pop)
|
* [`pop`](/docs/kcl-std/functions/std-array-pop)
|
||||||
* [`push`](/docs/kcl-std/push)
|
* [`push`](/docs/kcl-std/functions/std-array-push)
|
||||||
* [`reduce`](/docs/kcl-std/reduce)
|
* [`reduce`](/docs/kcl-std/functions/std-array-reduce)
|
||||||
* [**std::math**](/docs/kcl-std/modules/std-math)
|
* [**std::math**](/docs/kcl-std/modules/std-math)
|
||||||
* [`abs`](/docs/kcl-std/functions/std-math-abs)
|
* [`abs`](/docs/kcl-std/functions/std-math-abs)
|
||||||
* [`acos`](/docs/kcl-std/functions/std-math-acos)
|
* [`acos`](/docs/kcl-std/functions/std-math-acos)
|
||||||
@ -30,9 +30,9 @@ layout: manual
|
|||||||
* [`ceil`](/docs/kcl-std/functions/std-math-ceil)
|
* [`ceil`](/docs/kcl-std/functions/std-math-ceil)
|
||||||
* [`cos`](/docs/kcl-std/functions/std-math-cos)
|
* [`cos`](/docs/kcl-std/functions/std-math-cos)
|
||||||
* [`floor`](/docs/kcl-std/functions/std-math-floor)
|
* [`floor`](/docs/kcl-std/functions/std-math-floor)
|
||||||
* [`legAngX`](/docs/kcl-std/legAngX)
|
* [`legAngX`](/docs/kcl-std/functions/std-math-legAngX)
|
||||||
* [`legAngY`](/docs/kcl-std/legAngY)
|
* [`legAngY`](/docs/kcl-std/functions/std-math-legAngY)
|
||||||
* [`legLen`](/docs/kcl-std/legLen)
|
* [`legLen`](/docs/kcl-std/functions/std-math-legLen)
|
||||||
* [`ln`](/docs/kcl-std/functions/std-math-ln)
|
* [`ln`](/docs/kcl-std/functions/std-math-ln)
|
||||||
* [`log`](/docs/kcl-std/functions/std-math-log)
|
* [`log`](/docs/kcl-std/functions/std-math-log)
|
||||||
* [`log10`](/docs/kcl-std/functions/std-math-log10)
|
* [`log10`](/docs/kcl-std/functions/std-math-log10)
|
||||||
@ -128,6 +128,9 @@ layout: manual
|
|||||||
* [`E`](/docs/kcl-std/consts/std-math-E)
|
* [`E`](/docs/kcl-std/consts/std-math-E)
|
||||||
* [`PI`](/docs/kcl-std/consts/std-math-PI)
|
* [`PI`](/docs/kcl-std/consts/std-math-PI)
|
||||||
* [`TAU`](/docs/kcl-std/consts/std-math-TAU)
|
* [`TAU`](/docs/kcl-std/consts/std-math-TAU)
|
||||||
|
* [**std::sweep**](/docs/kcl-std/modules/std-sweep)
|
||||||
|
* [`sweep::SKETCH_PLANE`](/docs/kcl-std/consts/std-sweep-SKETCH_PLANE)
|
||||||
|
* [`sweep::TRAJECTORY`](/docs/kcl-std/consts/std-sweep-TRAJECTORY)
|
||||||
* [**std::turns**](/docs/kcl-std/modules/std-turns)
|
* [**std::turns**](/docs/kcl-std/modules/std-turns)
|
||||||
* [`turns::HALF_TURN`](/docs/kcl-std/consts/std-turns-HALF_TURN)
|
* [`turns::HALF_TURN`](/docs/kcl-std/consts/std-turns-HALF_TURN)
|
||||||
* [`turns::QUARTER_TURN`](/docs/kcl-std/consts/std-turns-QUARTER_TURN)
|
* [`turns::QUARTER_TURN`](/docs/kcl-std/consts/std-turns-QUARTER_TURN)
|
||||||
@ -140,12 +143,13 @@ See also the [types overview](/docs/kcl-lang/types)
|
|||||||
|
|
||||||
* [**Primitive types**](/docs/kcl-lang/types)
|
* [**Primitive types**](/docs/kcl-lang/types)
|
||||||
* [`End`](/docs/kcl-lang/types#End)
|
* [`End`](/docs/kcl-lang/types#End)
|
||||||
* [`ImportedGeometry`](/docs/kcl-lang/types#ImportedGeometry)
|
* [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry)
|
||||||
* [`Start`](/docs/kcl-lang/types#Start)
|
* [`Start`](/docs/kcl-lang/types#Start)
|
||||||
* [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator)
|
* [`TagDeclarator`](/docs/kcl-lang/types#TagDeclarator)
|
||||||
* [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier)
|
* [`TagIdentifier`](/docs/kcl-lang/types#TagIdentifier)
|
||||||
* [`any`](/docs/kcl-std/types/std-types-any)
|
* [`any`](/docs/kcl-std/types/std-types-any)
|
||||||
* [`bool`](/docs/kcl-std/types/std-types-bool)
|
* [`bool`](/docs/kcl-std/types/std-types-bool)
|
||||||
|
* [`fn`](/docs/kcl-std/types/std-types-fn)
|
||||||
* [`number`](/docs/kcl-std/types/std-types-number)
|
* [`number`](/docs/kcl-std/types/std-types-number)
|
||||||
* [`string`](/docs/kcl-std/types/std-types-string)
|
* [`string`](/docs/kcl-std/types/std-types-string)
|
||||||
* [`tag`](/docs/kcl-std/types/std-types-tag)
|
* [`tag`](/docs/kcl-std/types/std-types-tag)
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
title: "legAngX"
|
|
||||||
subtitle: "Function in std::math"
|
|
||||||
excerpt: "Compute the angle of the given leg for x."
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
Compute the angle of the given leg for x.
|
|
||||||
|
|
||||||
```kcl
|
|
||||||
legAngX(
|
|
||||||
hypotenuse: number,
|
|
||||||
leg: number,
|
|
||||||
): number
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Arguments
|
|
||||||
|
|
||||||
| Name | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `hypotenuse` | [`number`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse | Yes |
|
|
||||||
| `leg` | [`number`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side) | Yes |
|
|
||||||
|
|
||||||
### Returns
|
|
||||||
|
|
||||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```kcl
|
|
||||||
legAngX(hypotenuse = 5, leg = 3)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
title: "legAngY"
|
|
||||||
subtitle: "Function in std::math"
|
|
||||||
excerpt: "Compute the angle of the given leg for y."
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
Compute the angle of the given leg for y.
|
|
||||||
|
|
||||||
```kcl
|
|
||||||
legAngY(
|
|
||||||
hypotenuse: number,
|
|
||||||
leg: number,
|
|
||||||
): number
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Arguments
|
|
||||||
|
|
||||||
| Name | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `hypotenuse` | [`number`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse | Yes |
|
|
||||||
| `leg` | [`number`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side) | Yes |
|
|
||||||
|
|
||||||
### Returns
|
|
||||||
|
|
||||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```kcl
|
|
||||||
legAngY(hypotenuse = 5, leg = 3)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
title: "legLen"
|
|
||||||
subtitle: "Function in std::math"
|
|
||||||
excerpt: "Compute the length of the given leg."
|
|
||||||
layout: manual
|
|
||||||
---
|
|
||||||
|
|
||||||
Compute the length of the given leg.
|
|
||||||
|
|
||||||
```kcl
|
|
||||||
legLen(
|
|
||||||
hypotenuse: number,
|
|
||||||
leg: number,
|
|
||||||
): number
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Arguments
|
|
||||||
|
|
||||||
| Name | Type | Description | Required |
|
|
||||||
|----------|------|-------------|----------|
|
|
||||||
| `hypotenuse` | [`number`](/docs/kcl-std/types/std-types-number) | The length of the triangle's hypotenuse | Yes |
|
|
||||||
| `leg` | [`number`](/docs/kcl-std/types/std-types-number) | The length of one of the triangle's legs (i.e. non-hypotenuse side) | Yes |
|
|
||||||
|
|
||||||
### Returns
|
|
||||||
|
|
||||||
[`number`](/docs/kcl-std/types/std-types-number) - A number.
|
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
```kcl
|
|
||||||
legLen(hypotenuse = 5, leg = 3)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -12,8 +12,8 @@ Functions for manipulating arrays of values.
|
|||||||
|
|
||||||
## Functions and constants
|
## Functions and constants
|
||||||
|
|
||||||
* [`map`](/docs/kcl-std/map)
|
* [`map`](/docs/kcl-std/functions/std-array-map)
|
||||||
* [`pop`](/docs/kcl-std/pop)
|
* [`pop`](/docs/kcl-std/functions/std-array-pop)
|
||||||
* [`push`](/docs/kcl-std/push)
|
* [`push`](/docs/kcl-std/functions/std-array-push)
|
||||||
* [`reduce`](/docs/kcl-std/reduce)
|
* [`reduce`](/docs/kcl-std/functions/std-array-reduce)
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@ Functions for mathematical operations and some useful constants.
|
|||||||
* [`ceil`](/docs/kcl-std/functions/std-math-ceil)
|
* [`ceil`](/docs/kcl-std/functions/std-math-ceil)
|
||||||
* [`cos`](/docs/kcl-std/functions/std-math-cos)
|
* [`cos`](/docs/kcl-std/functions/std-math-cos)
|
||||||
* [`floor`](/docs/kcl-std/functions/std-math-floor)
|
* [`floor`](/docs/kcl-std/functions/std-math-floor)
|
||||||
* [`legAngX`](/docs/kcl-std/legAngX)
|
* [`legAngX`](/docs/kcl-std/functions/std-math-legAngX)
|
||||||
* [`legAngY`](/docs/kcl-std/legAngY)
|
* [`legAngY`](/docs/kcl-std/functions/std-math-legAngY)
|
||||||
* [`legLen`](/docs/kcl-std/legLen)
|
* [`legLen`](/docs/kcl-std/functions/std-math-legLen)
|
||||||
* [`ln`](/docs/kcl-std/functions/std-math-ln)
|
* [`ln`](/docs/kcl-std/functions/std-math-ln)
|
||||||
* [`log`](/docs/kcl-std/functions/std-math-log)
|
* [`log`](/docs/kcl-std/functions/std-math-log)
|
||||||
* [`log10`](/docs/kcl-std/functions/std-math-log10)
|
* [`log10`](/docs/kcl-std/functions/std-math-log10)
|
||||||
|
17
docs/kcl-std/modules/std-sweep.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
title: "sweep"
|
||||||
|
subtitle: "Module in std"
|
||||||
|
excerpt: ""
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Functions and constants
|
||||||
|
|
||||||
|
* [`sweep::SKETCH_PLANE`](/docs/kcl-std/consts/std-sweep-SKETCH_PLANE)
|
||||||
|
* [`sweep::TRAJECTORY`](/docs/kcl-std/consts/std-sweep-TRAJECTORY)
|
||||||
|
|
@ -18,6 +18,7 @@ Types can (optionally) be used to describe a function's arguments and returned v
|
|||||||
* [`Edge`](/docs/kcl-std/types/std-types-Edge)
|
* [`Edge`](/docs/kcl-std/types/std-types-Edge)
|
||||||
* [`Face`](/docs/kcl-std/types/std-types-Face)
|
* [`Face`](/docs/kcl-std/types/std-types-Face)
|
||||||
* [`Helix`](/docs/kcl-std/types/std-types-Helix)
|
* [`Helix`](/docs/kcl-std/types/std-types-Helix)
|
||||||
|
* [`ImportedGeometry`](/docs/kcl-std/types/std-types-ImportedGeometry)
|
||||||
* [`Plane`](/docs/kcl-std/types/std-types-Plane)
|
* [`Plane`](/docs/kcl-std/types/std-types-Plane)
|
||||||
* [`Point2d`](/docs/kcl-std/types/std-types-Point2d)
|
* [`Point2d`](/docs/kcl-std/types/std-types-Point2d)
|
||||||
* [`Point3d`](/docs/kcl-std/types/std-types-Point3d)
|
* [`Point3d`](/docs/kcl-std/types/std-types-Point3d)
|
||||||
@ -25,6 +26,7 @@ Types can (optionally) be used to describe a function's arguments and returned v
|
|||||||
* [`Solid`](/docs/kcl-std/types/std-types-Solid)
|
* [`Solid`](/docs/kcl-std/types/std-types-Solid)
|
||||||
* [`any`](/docs/kcl-std/types/std-types-any)
|
* [`any`](/docs/kcl-std/types/std-types-any)
|
||||||
* [`bool`](/docs/kcl-std/types/std-types-bool)
|
* [`bool`](/docs/kcl-std/types/std-types-bool)
|
||||||
|
* [`fn`](/docs/kcl-std/types/std-types-fn)
|
||||||
* [`number`](/docs/kcl-std/types/std-types-number)
|
* [`number`](/docs/kcl-std/types/std-types-number)
|
||||||
* [`string`](/docs/kcl-std/types/std-types-string)
|
* [`string`](/docs/kcl-std/types/std-types-string)
|
||||||
* [`tag`](/docs/kcl-std/types/std-types-tag)
|
* [`tag`](/docs/kcl-std/types/std-types-tag)
|
||||||
|
@ -11,12 +11,15 @@ Contains frequently used constants, functions for interacting with the KittyCAD
|
|||||||
|
|
||||||
The standard library is organised into modules (listed below), but most things are always available in KCL programs.
|
The standard library is organised into modules (listed below), but most things are always available in KCL programs.
|
||||||
|
|
||||||
|
You might also want the [KCL language reference](/docs/kcl-lang) or the [KCL guide]().
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
* [`array`](/docs/kcl-std/modules/std-array)
|
* [`array`](/docs/kcl-std/modules/std-array)
|
||||||
* [`math`](/docs/kcl-std/modules/std-math)
|
* [`math`](/docs/kcl-std/modules/std-math)
|
||||||
* [`sketch`](/docs/kcl-std/modules/std-sketch)
|
* [`sketch`](/docs/kcl-std/modules/std-sketch)
|
||||||
* [`solid`](/docs/kcl-std/modules/std-solid)
|
* [`solid`](/docs/kcl-std/modules/std-solid)
|
||||||
|
* [`sweep::sweep`](/docs/kcl-std/modules/std-sweep)
|
||||||
* [`transform`](/docs/kcl-std/modules/std-transform)
|
* [`transform`](/docs/kcl-std/modules/std-transform)
|
||||||
* [`turns::turns`](/docs/kcl-std/modules/std-turns)
|
* [`turns::turns`](/docs/kcl-std/modules/std-turns)
|
||||||
* [`types`](/docs/kcl-std/modules/std-types)
|
* [`types`](/docs/kcl-std/modules/std-types)
|
||||||
@ -35,7 +38,7 @@ The standard library is organised into modules (listed below), but most things a
|
|||||||
* [`appearance`](/docs/kcl-std/appearance)
|
* [`appearance`](/docs/kcl-std/appearance)
|
||||||
* [`assert`](/docs/kcl-std/assert)
|
* [`assert`](/docs/kcl-std/assert)
|
||||||
* [`assertIs`](/docs/kcl-std/assertIs)
|
* [`assertIs`](/docs/kcl-std/assertIs)
|
||||||
* [`clone`](/docs/kcl-std/clone)
|
* [`clone`](/docs/kcl-std/functions/std-clone)
|
||||||
* [`helix`](/docs/kcl-std/functions/std-helix)
|
* [`helix`](/docs/kcl-std/functions/std-helix)
|
||||||
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
* [`offsetPlane`](/docs/kcl-std/functions/std-offsetPlane)
|
||||||
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
* [`patternLinear2d`](/docs/kcl-std/patternLinear2d)
|
||||||
|
37352
docs/kcl-std/std.json
13
docs/kcl-std/types/std-types-ImportedGeometry.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
title: "ImportedGeometry"
|
||||||
|
subtitle: "Type in std::types"
|
||||||
|
excerpt: "Represents geometry which is defined using some other CAD system and imported into KCL."
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
Represents geometry which is defined using some other CAD system and imported into KCL.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -7,8 +7,25 @@ layout: manual
|
|||||||
|
|
||||||
An abstract plane.
|
An abstract plane.
|
||||||
|
|
||||||
A plane has a position and orientation in space defined by its origin and axes. A plane can be used
|
A plane has a position and orientation in space defined by its origin and axes. A plane is abstract
|
||||||
to sketch on.
|
in the sense that it is not part of the objects being drawn. A plane can be used to sketch on.
|
||||||
|
|
||||||
|
A plane can be created in several ways:
|
||||||
|
- you can use one of the default planes, e.g., `XY`.
|
||||||
|
- you can use `offsetPlane` to create a new plane offset from an existing one, e.g., `offsetPlane(XY, offset = 150)`.
|
||||||
|
- you can use negation to create a plane from an existing one which is identical but has an opposite normal
|
||||||
|
e.g., `-XY`.
|
||||||
|
- you can define an entirely custom plane, e.g.,
|
||||||
|
|
||||||
|
```js
|
||||||
|
myXY = {
|
||||||
|
origin = { x = 0, y = 0, z = 0 },
|
||||||
|
xAxis = { x = 1, y = 0, z = 0 },
|
||||||
|
yAxis = { x = 0, y = 1, z = 0 },
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Any object with appropriate `origin`, `xAxis`, and `yAxis` fields can be used as a plane.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
13
docs/kcl-std/types/std-types-fn.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
title: "fn"
|
||||||
|
subtitle: "Type in std::types"
|
||||||
|
excerpt: "The type of any function in KCL."
|
||||||
|
layout: manual
|
||||||
|
---
|
||||||
|
|
||||||
|
The type of any function in KCL.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -134,8 +134,6 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
await page.waitForTimeout(1000)
|
|
||||||
|
|
||||||
// Ensure badge is present
|
// Ensure badge is present
|
||||||
const codePaneButtonHolder = page.locator('#code-button-holder')
|
const codePaneButtonHolder = page.locator('#code-button-holder')
|
||||||
await expect(codePaneButtonHolder).toContainText('notification', {
|
await expect(codePaneButtonHolder).toContainText('notification', {
|
||||||
@ -158,10 +156,14 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
await expect(
|
await expect(
|
||||||
page
|
page
|
||||||
.getByText(
|
.getByText(
|
||||||
'Modeling command failed: [ApiError { error_code: InternalEngine, message: "Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis" }]'
|
'Solid3D revolve failed: sketch profile must lie entirely on one side of the revolution axis'
|
||||||
)
|
)
|
||||||
.first()
|
.first()
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
|
|
||||||
|
// Make sure ApiError is not on the page.
|
||||||
|
// This ensures we didn't nest the json
|
||||||
|
await expect(page.getByText('ApiError')).not.toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('When error is not in view WITH LINTS you can click the badge to scroll to it', async ({
|
test('When error is not in view WITH LINTS you can click the badge to scroll to it', async ({
|
||||||
@ -179,7 +181,7 @@ extrude001 = extrude(sketch001, length = 5)`
|
|||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
await scene.settled(cmdBar)
|
// await scene.settled(cmdBar)
|
||||||
|
|
||||||
// Ensure badge is present
|
// Ensure badge is present
|
||||||
const codePaneButtonHolder = page.locator('#code-button-holder')
|
const codePaneButtonHolder = page.locator('#code-button-holder')
|
||||||
|
@ -58,12 +58,6 @@ test(
|
|||||||
await expect(submitButton).toBeVisible()
|
await expect(submitButton).toBeVisible()
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Look out for the toast message
|
|
||||||
const exportingToastMessage = page.getByText(`Exporting...`)
|
|
||||||
const alreadyExportingToastMessage = page.getByText(`Already exporting`)
|
|
||||||
await expect(exportingToastMessage).toBeVisible()
|
|
||||||
await expect(alreadyExportingToastMessage).not.toBeVisible()
|
|
||||||
|
|
||||||
// Expect it to succeed
|
// Expect it to succeed
|
||||||
const errorToastMessage = page.getByText(`Error while exporting`)
|
const errorToastMessage = page.getByText(`Error while exporting`)
|
||||||
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
const engineErrorToastMessage = page.getByText(`Nothing to export`)
|
||||||
@ -71,8 +65,9 @@ test(
|
|||||||
await expect(engineErrorToastMessage).not.toBeVisible()
|
await expect(engineErrorToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
const successToastMessage = page.getByText(`Exported successfully`)
|
const successToastMessage = page.getByText(`Exported successfully`)
|
||||||
await expect(successToastMessage).toBeVisible()
|
await page.waitForTimeout(1_000)
|
||||||
await expect(exportingToastMessage).not.toBeVisible()
|
const count = await successToastMessage.count()
|
||||||
|
await expect(count).toBeGreaterThanOrEqual(1)
|
||||||
|
|
||||||
// Check for the exported file
|
// Check for the exported file
|
||||||
const firstFileFullPath = path.resolve(
|
const firstFileFullPath = path.resolve(
|
||||||
@ -141,7 +136,9 @@ test(
|
|||||||
await expect(engineErrorToastMessage).not.toBeVisible()
|
await expect(engineErrorToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
const successToastMessage = page.getByText(`Exported successfully`)
|
const successToastMessage = page.getByText(`Exported successfully`)
|
||||||
await expect(successToastMessage).toBeVisible()
|
await page.waitForTimeout(1_000)
|
||||||
|
const count = await successToastMessage.count()
|
||||||
|
await expect(count).toBeGreaterThanOrEqual(1)
|
||||||
await expect(exportingToastMessage).not.toBeVisible()
|
await expect(exportingToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
// Check for the exported file=
|
// Check for the exported file=
|
||||||
|
@ -1533,7 +1533,6 @@ sketch001 = startSketchOn(XZ)
|
|||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
await scene.connectionEstablished()
|
||||||
await scene.settled(cmdBar)
|
|
||||||
|
|
||||||
await scene.expectPixelColor(
|
await scene.expectPixelColor(
|
||||||
TEST_COLORS.DARK_MODE_BKGD,
|
TEST_COLORS.DARK_MODE_BKGD,
|
||||||
|
@ -155,6 +155,12 @@ export class CmdBarFixture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeCmdBar = async () => {
|
||||||
|
const cmdBarCloseBtn = this.page.getByTestId('command-bar-close-button')
|
||||||
|
await cmdBarCloseBtn.click()
|
||||||
|
await expect(this.cmdBarElement).not.toBeVisible()
|
||||||
|
}
|
||||||
|
|
||||||
get cmdSearchInput() {
|
get cmdSearchInput() {
|
||||||
return this.page.getByTestId('cmd-bar-search')
|
return this.page.getByTestId('cmd-bar-search')
|
||||||
}
|
}
|
||||||
@ -298,4 +304,27 @@ export class CmdBarFixture {
|
|||||||
`Monitoring text-to-cad API requests. Output will be saved to: ${outputPath}`
|
`Monitoring text-to-cad API requests. Output will be saved to: ${outputPath}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async toBeOpened() {
|
||||||
|
// Check that the command bar is opened
|
||||||
|
await expect(this.cmdBarElement).toBeVisible({ timeout: 10_000 })
|
||||||
|
}
|
||||||
|
|
||||||
|
async expectArgValue(value: string) {
|
||||||
|
// Check the placeholder project name exists
|
||||||
|
const actualArgument = await this.cmdBarElement
|
||||||
|
.getByTestId('cmd-bar-arg-value')
|
||||||
|
.inputValue()
|
||||||
|
const expectedArgument = value
|
||||||
|
expect(actualArgument).toBe(expectedArgument)
|
||||||
|
}
|
||||||
|
|
||||||
|
async expectCommandName(value: string) {
|
||||||
|
// Check the placeholder project name exists
|
||||||
|
const actual = await this.cmdBarElement
|
||||||
|
.getByTestId('command-name')
|
||||||
|
.textContent()
|
||||||
|
const expected = value
|
||||||
|
expect(actual).toBe(expected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ export class HomePageFixture {
|
|||||||
projectTextName!: Locator
|
projectTextName!: Locator
|
||||||
sortByDateBtn!: Locator
|
sortByDateBtn!: Locator
|
||||||
sortByNameBtn!: Locator
|
sortByNameBtn!: Locator
|
||||||
|
appHeader!: Locator
|
||||||
tutorialBtn!: Locator
|
tutorialBtn!: Locator
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
@ -44,6 +45,7 @@ export class HomePageFixture {
|
|||||||
|
|
||||||
this.sortByDateBtn = this.page.getByTestId('home-sort-by-modified')
|
this.sortByDateBtn = this.page.getByTestId('home-sort-by-modified')
|
||||||
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
this.sortByNameBtn = this.page.getByTestId('home-sort-by-name')
|
||||||
|
this.appHeader = this.page.getByTestId('app-header')
|
||||||
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
this.tutorialBtn = this.page.getByTestId('home-tutorial-button')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,4 +127,11 @@ export class HomePageFixture {
|
|||||||
|
|
||||||
await this.createAndGoToProject(name)
|
await this.createAndGoToProject(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNativeFileMenuCreated = async () => {
|
||||||
|
await expect(this.appHeader).toHaveAttribute(
|
||||||
|
'data-native-file-menu',
|
||||||
|
'true'
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ export class SceneFixture {
|
|||||||
public networkToggleConnected!: Locator
|
public networkToggleConnected!: Locator
|
||||||
public engineConnectionsSpinner!: Locator
|
public engineConnectionsSpinner!: Locator
|
||||||
public startEditSketchBtn!: Locator
|
public startEditSketchBtn!: Locator
|
||||||
|
public appHeader!: Locator
|
||||||
|
|
||||||
constructor(page: Page) {
|
constructor(page: Page) {
|
||||||
this.page = page
|
this.page = page
|
||||||
@ -57,6 +58,7 @@ export class SceneFixture {
|
|||||||
this.startEditSketchBtn = page
|
this.startEditSketchBtn = page
|
||||||
.getByRole('button', { name: 'Start Sketch' })
|
.getByRole('button', { name: 'Start Sketch' })
|
||||||
.or(page.getByRole('button', { name: 'Edit Sketch' }))
|
.or(page.getByRole('button', { name: 'Edit Sketch' }))
|
||||||
|
this.appHeader = this.page.getByTestId('app-header')
|
||||||
}
|
}
|
||||||
private _serialiseScene = async (): Promise<SceneSerialised> => {
|
private _serialiseScene = async (): Promise<SceneSerialised> => {
|
||||||
const camera = await this.getCameraInfo()
|
const camera = await this.getCameraInfo()
|
||||||
@ -280,6 +282,13 @@ export class SceneFixture {
|
|||||||
await expect(buttonToTest).toBeVisible()
|
await expect(buttonToTest).toBeVisible()
|
||||||
await buttonToTest.click()
|
await buttonToTest.click()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNativeFileMenuCreated = async () => {
|
||||||
|
await expect(this.appHeader).toHaveAttribute(
|
||||||
|
'data-native-file-menu',
|
||||||
|
'true'
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isColourArray(
|
function isColourArray(
|
||||||
|
@ -6,7 +6,6 @@ test.describe('Onboarding tests', () => {
|
|||||||
homePage,
|
homePage,
|
||||||
toolbar,
|
toolbar,
|
||||||
editor,
|
editor,
|
||||||
scene,
|
|
||||||
tronApp,
|
tronApp,
|
||||||
}) => {
|
}) => {
|
||||||
if (!tronApp) {
|
if (!tronApp) {
|
||||||
@ -62,7 +61,6 @@ test.describe('Onboarding tests', () => {
|
|||||||
await editor.expectEditor.toContain('@settings(defaultLengthUnit = in)', {
|
await editor.expectEditor.toContain('@settings(defaultLengthUnit = in)', {
|
||||||
shouldNormalise: true,
|
shouldNormalise: true,
|
||||||
})
|
})
|
||||||
await scene.connectionEstablished()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Go home and verify we still see the tutorial button, then begin it.', async () => {
|
await test.step('Go home and verify we still see the tutorial button, then begin it.', async () => {
|
||||||
@ -132,9 +130,7 @@ test.describe('Onboarding tests', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Dismiss the onboarding', async () => {
|
await test.step('Dismiss the onboarding', async () => {
|
||||||
await postDismissToast.waitFor({ state: 'hidden' })
|
|
||||||
await page.keyboard.press('Escape')
|
await page.keyboard.press('Escape')
|
||||||
await expect(postDismissToast).toBeVisible()
|
|
||||||
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
||||||
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
||||||
})
|
})
|
||||||
@ -162,13 +158,10 @@ test.describe('Onboarding tests', () => {
|
|||||||
await test.step('Gets to the onboarding start', async () => {
|
await test.step('Gets to the onboarding start', async () => {
|
||||||
await expect(toolbar.projectName).toContainText('tutorial-project')
|
await expect(toolbar.projectName).toContainText('tutorial-project')
|
||||||
await expect(tutorialWelcomeHeading).toBeVisible()
|
await expect(tutorialWelcomeHeading).toBeVisible()
|
||||||
await scene.connectionEstablished()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Dismiss the onboarding', async () => {
|
await test.step('Dismiss the onboarding', async () => {
|
||||||
await postDismissToast.waitFor({ state: 'hidden' })
|
|
||||||
await page.keyboard.press('Escape')
|
await page.keyboard.press('Escape')
|
||||||
await expect(postDismissToast).toBeVisible()
|
|
||||||
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
await expect(page.getByTestId('onboarding-content')).not.toBeVisible()
|
||||||
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
await expect.poll(() => page.url()).not.toContain('/onboarding')
|
||||||
})
|
})
|
||||||
|
@ -1931,50 +1931,37 @@ sketch002 = startSketchOn(XZ)
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`Sweep point-and-click failing validation`, async ({
|
test(`Sweep point-and-click helix`, async ({
|
||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
scene,
|
scene,
|
||||||
|
editor,
|
||||||
toolbar,
|
toolbar,
|
||||||
cmdBar,
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
const initialCode = `@settings(defaultLengthUnit = in)
|
const circleCode = `circle(sketch001, center = [0, -1], radius = .1)`
|
||||||
sketch001 = startSketchOn(YZ)
|
const initialCode = `helix001 = helix(
|
||||||
|> circle(
|
axis = X,
|
||||||
center = [0, 0],
|
radius = 1,
|
||||||
radius = 500
|
length = 10,
|
||||||
|
revolutions = 10,
|
||||||
|
angleStart = 0,
|
||||||
|
ccw = false,
|
||||||
)
|
)
|
||||||
sketch002 = startSketchOn(XZ)
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfile(at = [0, 0])
|
profile001 = ${circleCode}`
|
||||||
|> xLine(length = -500)
|
const sweepDeclaration = 'sweep001 = sweep(profile001, path = helix001)'
|
||||||
|> line(endAbsolute = [-2000, 500])
|
|
||||||
`
|
|
||||||
await context.addInitScript((initialCode) => {
|
await context.addInitScript((initialCode) => {
|
||||||
localStorage.setItem('persistCode', initialCode)
|
localStorage.setItem('persistCode', initialCode)
|
||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await scene.settled(cmdBar)
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
await test.step(`Add sweep through the command bar flow`, async () => {
|
||||||
const testPoint = { x: 700, y: 250 }
|
await toolbar.openPane('feature-tree')
|
||||||
const [clickOnSketch1] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
||||||
const [clickOnSketch2] = scene.makeMouseHelpers(
|
|
||||||
testPoint.x - 50,
|
|
||||||
testPoint.y
|
|
||||||
)
|
|
||||||
|
|
||||||
await test.step(`Look for sketch001`, async () => {
|
|
||||||
await toolbar.closePane('code')
|
|
||||||
await scene.expectPixelColor([53, 53, 53], testPoint, 15)
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step(`Go through the command bar flow and fail validation with a toast`, async () => {
|
|
||||||
await toolbar.sweepButton.click()
|
await toolbar.sweepButton.click()
|
||||||
await expect
|
|
||||||
.poll(() => page.getByText('Please select one').count())
|
|
||||||
.toBe(1)
|
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
currentArgKey: 'sketches',
|
currentArgKey: 'sketches',
|
||||||
@ -1987,7 +1974,8 @@ sketch002 = startSketchOn(XZ)
|
|||||||
highlightedHeaderArg: 'sketches',
|
highlightedHeaderArg: 'sketches',
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
})
|
})
|
||||||
await clickOnSketch1()
|
await editor.scrollToText(circleCode)
|
||||||
|
await page.getByText(circleCode).click()
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await cmdBar.expectState({
|
await cmdBar.expectState({
|
||||||
commandName: 'Sweep',
|
commandName: 'Sweep',
|
||||||
@ -2001,11 +1989,39 @@ sketch002 = startSketchOn(XZ)
|
|||||||
highlightedHeaderArg: 'path',
|
highlightedHeaderArg: 'path',
|
||||||
stage: 'arguments',
|
stage: 'arguments',
|
||||||
})
|
})
|
||||||
await clickOnSketch2()
|
const helix = await toolbar.getFeatureTreeOperation('Helix', 0)
|
||||||
|
await helix.click()
|
||||||
|
await cmdBar.expectState({
|
||||||
|
commandName: 'Sweep',
|
||||||
|
currentArgKey: 'path',
|
||||||
|
currentArgValue: '',
|
||||||
|
headerArguments: {
|
||||||
|
Sectional: '',
|
||||||
|
Sketches: '1 face',
|
||||||
|
Path: '',
|
||||||
|
},
|
||||||
|
highlightedHeaderArg: 'path',
|
||||||
|
stage: 'arguments',
|
||||||
|
})
|
||||||
await cmdBar.progressCmdBar()
|
await cmdBar.progressCmdBar()
|
||||||
await expect(
|
await cmdBar.expectState({
|
||||||
page.getByText('Unable to sweep with the current selection. Reason:')
|
commandName: 'Sweep',
|
||||||
).toBeVisible()
|
headerArguments: {
|
||||||
|
Sketches: '1 face',
|
||||||
|
Path: '1 helix',
|
||||||
|
Sectional: '',
|
||||||
|
},
|
||||||
|
stage: 'review',
|
||||||
|
})
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
|
await editor.expectEditor.toContain(sweepDeclaration)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Delete sweep via feature tree selection', async () => {
|
||||||
|
const sweep = await toolbar.getFeatureTreeOperation('Sweep', 0)
|
||||||
|
await sweep.click()
|
||||||
|
await page.keyboard.press('Delete')
|
||||||
|
await editor.expectEditor.not.toContain(sweepDeclaration)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -3627,67 +3643,6 @@ profile001 = startProfile(sketch001, at = [-20, 20])
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test(`Shell dry-run validation rejects sweeps`, async ({
|
|
||||||
context,
|
|
||||||
page,
|
|
||||||
homePage,
|
|
||||||
scene,
|
|
||||||
editor,
|
|
||||||
toolbar,
|
|
||||||
cmdBar,
|
|
||||||
}) => {
|
|
||||||
const initialCode = `sketch001 = startSketchOn(YZ)
|
|
||||||
|> circle(
|
|
||||||
center = [0, 0],
|
|
||||||
radius = 500
|
|
||||||
)
|
|
||||||
sketch002 = startSketchOn(XZ)
|
|
||||||
|> startProfile(at = [0, 0])
|
|
||||||
|> xLine(length = -2000)
|
|
||||||
sweep001 = sweep(sketch001, path = sketch002)
|
|
||||||
`
|
|
||||||
await context.addInitScript((initialCode) => {
|
|
||||||
localStorage.setItem('persistCode', initialCode)
|
|
||||||
}, initialCode)
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
|
||||||
await homePage.goToModelingScene()
|
|
||||||
await scene.settled(cmdBar)
|
|
||||||
|
|
||||||
// One dumb hardcoded screen pixel value
|
|
||||||
const testPoint = { x: 500, y: 250 }
|
|
||||||
const [clickOnSweep] = scene.makeMouseHelpers(testPoint.x, testPoint.y)
|
|
||||||
|
|
||||||
await test.step(`Confirm sweep exists`, async () => {
|
|
||||||
await toolbar.closePane('code')
|
|
||||||
await scene.expectPixelColor([231, 231, 231], testPoint, 15)
|
|
||||||
})
|
|
||||||
|
|
||||||
await test.step(`Go through the Shell flow and fail validation with a toast`, async () => {
|
|
||||||
await toolbar.shellButton.click()
|
|
||||||
await expect
|
|
||||||
.poll(() => page.getByText('Please select one').count())
|
|
||||||
.toBe(1)
|
|
||||||
await cmdBar.expectState({
|
|
||||||
stage: 'arguments',
|
|
||||||
currentArgKey: 'selection',
|
|
||||||
currentArgValue: '',
|
|
||||||
headerArguments: {
|
|
||||||
Selection: '',
|
|
||||||
Thickness: '',
|
|
||||||
},
|
|
||||||
highlightedHeaderArg: 'selection',
|
|
||||||
commandName: 'Shell',
|
|
||||||
})
|
|
||||||
await clickOnSweep()
|
|
||||||
await page.waitForTimeout(500)
|
|
||||||
await cmdBar.progressCmdBar()
|
|
||||||
await expect(
|
|
||||||
page.getByText('Unable to shell with the current selection. Reason:')
|
|
||||||
).toBeVisible()
|
|
||||||
await page.waitForTimeout(1000)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
test.describe('Revolve point and click workflows', () => {
|
test.describe('Revolve point and click workflows', () => {
|
||||||
test('Base case workflow, auto spam continue in command bar', async ({
|
test('Base case workflow, auto spam continue in command bar', async ({
|
||||||
context,
|
context,
|
||||||
@ -4943,4 +4898,34 @@ path001 = startProfile(sketch001, at = [0, 0])
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test(`Point and click codemods can't run on KCL errors`, async ({
|
||||||
|
context,
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
editor,
|
||||||
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
const badCode = `sketch001 = startSketchOn(XZ)
|
||||||
|
profile001 = circle(sketch001, center = [0, 0], radius = 1)
|
||||||
|
extrude001 = extrude(profile001 length = 1)`
|
||||||
|
await context.addInitScript((initialCode) => {
|
||||||
|
localStorage.setItem('persistCode', initialCode)
|
||||||
|
}, badCode)
|
||||||
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
|
await test.step(`Start Sketch is disabled`, async () => {
|
||||||
|
await expect(toolbar.startSketchBtn).not.toBeEnabled()
|
||||||
|
await editor.expectEditor.toContain(badCode, { shouldNormalise: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step(`Helix is disabled`, async () => {
|
||||||
|
await expect(toolbar.helixButton).not.toBeEnabled()
|
||||||
|
await editor.expectEditor.toContain(badCode, { shouldNormalise: true })
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -1818,7 +1818,6 @@ test(
|
|||||||
'extrude-custom-plane.kcl',
|
'extrude-custom-plane.kcl',
|
||||||
'extrude-inside-fn-with-tags.kcl',
|
'extrude-inside-fn-with-tags.kcl',
|
||||||
'fillet-and-shell.kcl',
|
'fillet-and-shell.kcl',
|
||||||
'fillet_duplicate_tags.kcl',
|
|
||||||
'focusrite_scarlett_mounting_bracket.kcl',
|
'focusrite_scarlett_mounting_bracket.kcl',
|
||||||
'function_sketch.kcl',
|
'function_sketch.kcl',
|
||||||
'function_sketch_with_position.kcl',
|
'function_sketch_with_position.kcl',
|
||||||
@ -1826,7 +1825,6 @@ test(
|
|||||||
'helix_defaults.kcl',
|
'helix_defaults.kcl',
|
||||||
'helix_defaults_negative_extrude.kcl',
|
'helix_defaults_negative_extrude.kcl',
|
||||||
'helix_with_length.kcl',
|
'helix_with_length.kcl',
|
||||||
'i_shape.kcl',
|
|
||||||
'kittycad_svg.kcl',
|
'kittycad_svg.kcl',
|
||||||
'lego.kcl',
|
'lego.kcl',
|
||||||
'lsystem.kcl',
|
'lsystem.kcl',
|
||||||
|
@ -99,6 +99,8 @@ test.describe('edit with AI example snapshots', () => {
|
|||||||
await test.step('fire off edit prompt', async () => {
|
await test.step('fire off edit prompt', async () => {
|
||||||
await cmdBar.captureTextToCadRequestSnapshot(test.info())
|
await cmdBar.captureTextToCadRequestSnapshot(test.info())
|
||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
// being specific about the color with a hex means asserting pixel color is more stable
|
// being specific about the color with a hex means asserting pixel color is more stable
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
|
@ -88,6 +88,8 @@ test.describe('Prompt-to-edit tests', () => {
|
|||||||
|
|
||||||
await test.step('fire off edit prompt', async () => {
|
await test.step('fire off edit prompt', async () => {
|
||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
// being specific about the color with a hex means asserting pixel color is more stable
|
// being specific about the color with a hex means asserting pixel color is more stable
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
@ -165,6 +167,8 @@ test.describe('Prompt-to-edit tests', () => {
|
|||||||
|
|
||||||
await test.step('fire of bad prompt', async () => {
|
await test.step('fire of bad prompt', async () => {
|
||||||
await cmdBar.openCmdBar('promptToEdit')
|
await cmdBar.openCmdBar('promptToEdit')
|
||||||
|
await page.waitForTimeout(100)
|
||||||
|
await cmdBar.progressCmdBar()
|
||||||
await page
|
await page
|
||||||
.getByTestId('cmd-bar-arg-value')
|
.getByTestId('cmd-bar-arg-value')
|
||||||
.fill('ansheusha asnthuatshoeuhtaoetuhthaeu laughs in dvorak')
|
.fill('ansheusha asnthuatshoeuhtaoetuhthaeu laughs in dvorak')
|
||||||
|
@ -19,11 +19,12 @@ test.describe('Regression tests', () => {
|
|||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
}) => {
|
}) => {
|
||||||
// because the model has `line([0,0]..` it is valid code, but the model is invalid
|
// because the model has `line([0,0]..` it is valid code, but the model is invalid
|
||||||
// regression test for https://github.com/KittyCAD/modeling-app/issues/3251
|
// regression test for https://github.com/KittyCAD/modeling-app/issues/3251
|
||||||
// Since the bad model also found as issue with the artifact graph, which in tern blocked the editor diognostics
|
// Since the bad model also found as issue with the artifact graph, which in tern blocked the editor diognostics
|
||||||
const u = await getUtils(page)
|
// const u = await getUtils(page)
|
||||||
await context.addInitScript(async () => {
|
await context.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -40,7 +41,8 @@ test.describe('Regression tests', () => {
|
|||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
await scene.connectionEstablished()
|
||||||
|
// await u.waitForPageLoad()
|
||||||
|
|
||||||
// error in guter
|
// error in guter
|
||||||
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
|
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
|
||||||
@ -51,8 +53,11 @@ test.describe('Regression tests', () => {
|
|||||||
// the close doesn't work
|
// the close doesn't work
|
||||||
// when https://github.com/KittyCAD/modeling-app/issues/3268 is closed
|
// when https://github.com/KittyCAD/modeling-app/issues/3268 is closed
|
||||||
// this test will need updating
|
// this test will need updating
|
||||||
const crypticErrorText = `ApiError`
|
const crypticErrorText = `Cannot close a path that is non-planar or with duplicate vertices.
|
||||||
|
Internal engine error on request`
|
||||||
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
await expect(page.getByText(crypticErrorText).first()).toBeVisible()
|
||||||
|
// Ensure we didn't nest the json.
|
||||||
|
await expect(page.getByText('ApiError')).not.toBeVisible()
|
||||||
})
|
})
|
||||||
test('user should not have to press down twice in cmdbar', async ({
|
test('user should not have to press down twice in cmdbar', async ({
|
||||||
page,
|
page,
|
||||||
@ -185,8 +190,8 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
page.locator('.pretty-json-container >> text=myVar:"67')
|
page.locator('.pretty-json-container >> text=myVar:"67')
|
||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
})
|
})
|
||||||
test('ProgramMemory can be serialised', async ({ page, homePage }) => {
|
test('ProgramMemory can be serialised', async ({ page, homePage, scene }) => {
|
||||||
const u = await getUtils(page)
|
// const u = await getUtils(page)
|
||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
@ -211,11 +216,12 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
// Listen for all console events and push the message text to an array
|
// Listen for all console events and push the message text to an array
|
||||||
page.on('console', (message) => messages.push(message.text()))
|
page.on('console', (message) => messages.push(message.text()))
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
await u.waitForPageLoad()
|
// await u.waitForPageLoad()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
// wait for execution done
|
// wait for execution done
|
||||||
await u.openDebugPanel()
|
// await u.openDebugPanel()
|
||||||
await u.expectCmdLog('[data-message-type="execution-done"]')
|
// await u.expectCmdLog('[data-message-type="execution-done"]')
|
||||||
|
|
||||||
const forbiddenMessages = ['cannot serialize tagged newtype variant']
|
const forbiddenMessages = ['cannot serialize tagged newtype variant']
|
||||||
forbiddenMessages.forEach((forbiddenMessage) => {
|
forbiddenMessages.forEach((forbiddenMessage) => {
|
||||||
@ -229,6 +235,7 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
context,
|
context,
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
scene,
|
||||||
}) => {
|
}) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
// const PUR = 400 / 37.5 //pixeltoUnitRatio
|
// const PUR = 400 / 37.5 //pixeltoUnitRatio
|
||||||
@ -247,11 +254,10 @@ extrude001 = extrude(sketch001, length = 50)
|
|||||||
shell(exampleSketch, faces = ['end'], thickness = 0.25)`
|
shell(exampleSketch, faces = ['end'], thickness = 0.25)`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
await homePage.goToModelingScene()
|
|
||||||
await u.waitForPageLoad()
|
|
||||||
|
|
||||||
// error in guter
|
// error in guter
|
||||||
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
|
await expect(page.locator('.cm-lint-marker-error')).toBeVisible({
|
||||||
timeout: 1_000,
|
timeout: 1_000,
|
||||||
@ -329,10 +335,10 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
)
|
)
|
||||||
|
|
||||||
const websocketPromise = page.waitForEvent('websocket')
|
const websocketPromise = page.waitForEvent('websocket')
|
||||||
await toolbar.closePane('code')
|
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await toolbar.closePane('code')
|
||||||
const websocket = await websocketPromise
|
const websocket = await websocketPromise
|
||||||
|
|
||||||
await scene.connectionEstablished()
|
await scene.connectionEstablished()
|
||||||
@ -452,12 +458,10 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
|
|
||||||
// Click the stl.
|
// Click the stl.
|
||||||
await expect(stlOption).toBeVisible()
|
await expect(stlOption).toBeVisible()
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Click the checkbox
|
// Click the checkbox
|
||||||
await expect(submitButton).toBeVisible()
|
await expect(submitButton).toBeVisible()
|
||||||
|
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
|
||||||
// Find the toast.
|
// Find the toast.
|
||||||
@ -465,11 +469,13 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
await expect(exportingToastMessage).toBeVisible()
|
await expect(exportingToastMessage).toBeVisible()
|
||||||
|
|
||||||
// Expect it to succeed.
|
// Expect it to succeed.
|
||||||
await expect(exportingToastMessage).not.toBeVisible({ timeout: 15_000 })
|
await expect(exportingToastMessage).not.toBeVisible()
|
||||||
await expect(engineErrorToastMessage).not.toBeVisible()
|
await expect(engineErrorToastMessage).not.toBeVisible()
|
||||||
|
|
||||||
const successToastMessage = page.getByText(`Exported successfully`)
|
const successToastMessage = page.getByText(`Exported successfully`)
|
||||||
await expect(successToastMessage).toBeVisible()
|
await page.waitForTimeout(1_000)
|
||||||
|
const count = await successToastMessage.count()
|
||||||
|
await expect(count).toBeGreaterThanOrEqual(1)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// We updated this test such that you can have multiple exports going at once.
|
// We updated this test such that you can have multiple exports going at once.
|
||||||
@ -545,14 +551,15 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
expect(alreadyExportingToastMessage).not.toBeVisible(),
|
||||||
])
|
])
|
||||||
|
|
||||||
await expect(successToastMessage).toHaveCount(2)
|
const count = await successToastMessage.count()
|
||||||
|
await expect(count).toBeGreaterThanOrEqual(2)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test(
|
test(
|
||||||
`Network health indicator only appears in modeling view`,
|
`Network health indicator only appears in modeling view`,
|
||||||
{ tag: '@electron' },
|
{ tag: '@electron' },
|
||||||
async ({ context, page }, testInfo) => {
|
async ({ context, page }) => {
|
||||||
await context.folderSetupFn(async (dir) => {
|
await context.folderSetupFn(async (dir) => {
|
||||||
const bracketDir = path.join(dir, 'bracket')
|
const bracketDir = path.join(dir, 'bracket')
|
||||||
await fsp.mkdir(bracketDir, { recursive: true })
|
await fsp.mkdir(bracketDir, { recursive: true })
|
||||||
@ -561,9 +568,7 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
path.join(bracketDir, 'main.kcl')
|
path.join(bracketDir, 'main.kcl')
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
await page.setBodyDimensions({ width: 1200, height: 500 })
|
await page.setBodyDimensions({ width: 1200, height: 500 })
|
||||||
const u = await getUtils(page)
|
|
||||||
|
|
||||||
// Locators
|
// Locators
|
||||||
const projectsHeading = page.getByRole('heading', {
|
const projectsHeading = page.getByRole('heading', {
|
||||||
@ -583,10 +588,8 @@ extrude002 = extrude(profile002, length = 150)
|
|||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Check the modeling view', async () => {
|
await test.step('Check the modeling view', async () => {
|
||||||
|
await expect(projectsHeading).not.toBeVisible()
|
||||||
await expect(networkHealthIndicator).toBeVisible()
|
await expect(networkHealthIndicator).toBeVisible()
|
||||||
await expect(networkHealthIndicator).toContainText('Problem')
|
|
||||||
await u.waitForPageLoad()
|
|
||||||
await expect(networkHealthIndicator).toContainText('Connected')
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -841,6 +844,40 @@ washer = extrude(washerSketch, length = thicknessMax)`
|
|||||||
await editor.expectEditor.toContain('@settings(defaultLengthUnit = yd)')
|
await editor.expectEditor.toContain('@settings(defaultLengthUnit = yd)')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('Exiting existing sketch without editing should not delete it', async ({
|
||||||
|
page,
|
||||||
|
editor,
|
||||||
|
homePage,
|
||||||
|
context,
|
||||||
|
toolbar,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
await context.folderSetupFn(async (dir) => {
|
||||||
|
const testDir = path.join(dir, 'test')
|
||||||
|
await fsp.mkdir(testDir, { recursive: true })
|
||||||
|
await fsp.writeFile(
|
||||||
|
path.join(testDir, 'main.kcl'),
|
||||||
|
`s1 = startSketchOn(XY)
|
||||||
|
|> startProfile(at = [0, 25])
|
||||||
|
|> xLine(endAbsolute = -15 + 1.5)
|
||||||
|
s2 = startSketchOn(XY)
|
||||||
|
|> startProfile(at = [25, 0])
|
||||||
|
|> yLine(endAbsolute = -15 + 1.5)`,
|
||||||
|
'utf-8'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await homePage.openProject('test')
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
await toolbar.waitForFeatureTreeToBeBuilt()
|
||||||
|
await toolbar.editSketch(1)
|
||||||
|
await page.waitForTimeout(1000) // Just hang out for a second
|
||||||
|
await toolbar.exitSketch()
|
||||||
|
|
||||||
|
await editor.expectEditor.toContain('s2 = startSketchOn(XY)')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
async function clickExportButton(page: Page) {
|
async function clickExportButton(page: Page) {
|
||||||
|
@ -1365,18 +1365,18 @@ solid001 = subtract([extrude001], tools = [extrude002])
|
|||||||
await page.addInitScript(async () => {
|
await page.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
'persistCode',
|
'persistCode',
|
||||||
`fn in2mm = (inches) => {
|
`fn in2mm(@inches) {
|
||||||
return inches * 25.4
|
return inches * 25.4
|
||||||
}
|
}
|
||||||
|
|
||||||
const railTop = in2mm(.748)
|
railTop = in2mm(.748)
|
||||||
const railSide = in2mm(.024)
|
railSide = in2mm(.024)
|
||||||
const railBaseWidth = in2mm(.612)
|
railBaseWidth = in2mm(.612)
|
||||||
const railWideWidth = in2mm(.835)
|
railWideWidth = in2mm(.835)
|
||||||
const railBaseLength = in2mm(.200)
|
railBaseLength = in2mm(.200)
|
||||||
const railClampable = in2mm(.200)
|
railClampable = in2mm(.200)
|
||||||
|
|
||||||
const rail = startSketchOn(XZ)
|
rail = startSketchOn(XZ)
|
||||||
|> startProfile(at = [-railTop / 2, railClampable + railBaseLength])
|
|> startProfile(at = [-railTop / 2, railClampable + railBaseLength])
|
||||||
|> line(endAbsolute = [
|
|> line(endAbsolute = [
|
||||||
railTop / 2,
|
railTop / 2,
|
||||||
@ -3496,6 +3496,69 @@ profile001 = startProfile(sketch001, at = [-102.72, 237.44])
|
|||||||
).toBeVisible()
|
).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Ensure feature tree is not showing previous file's content when switching to a file with KCL errors.
|
||||||
|
test('Feature tree shows correct sketch count per file', async ({
|
||||||
|
context,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
|
||||||
|
// Setup project with files.
|
||||||
|
const GOOD_KCL = `sketch001 = startSketchOn(XZ)
|
||||||
|
profile001 = startProfile(sketch001, at = [220.81, 253.8])
|
||||||
|
|> line(end = [132.84, -151.31])
|
||||||
|
|> line(end = [25.51, 167.15])
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()
|
||||||
|
sketch002 = startSketchOn(XZ)
|
||||||
|
profile002 = startProfile(sketch002, at = [158.35, -70.82])
|
||||||
|
|> line(end = [73.9, -152.19])
|
||||||
|
|> line(end = [85.33, 135.48])
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()`
|
||||||
|
|
||||||
|
const ERROR_KCL = `sketch001 = startSketchOn(XZ)
|
||||||
|
profile001 = startProfile(sketch001, at = [127.56, 179.02])
|
||||||
|
|> line(end = [132.84, -112.6])
|
||||||
|
|> line(end = [85.33, 234.01])
|
||||||
|
|> line(enfd = [-137.23, -54.55])`
|
||||||
|
|
||||||
|
await context.folderSetupFn(async (dir) => {
|
||||||
|
const projectDir = path.join(dir, 'multi-file-sketch-test')
|
||||||
|
await fs.mkdir(projectDir, { recursive: true })
|
||||||
|
await Promise.all([
|
||||||
|
fs.writeFile(path.join(projectDir, 'good.kcl'), GOOD_KCL, 'utf-8'),
|
||||||
|
fs.writeFile(path.join(projectDir, 'error.kcl'), ERROR_KCL, 'utf-8'),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.setBodyDimensions({ width: 1000, height: 800 })
|
||||||
|
|
||||||
|
await homePage.openProject('multi-file-sketch-test')
|
||||||
|
await scene.connectionEstablished()
|
||||||
|
|
||||||
|
await u.closeDebugPanel()
|
||||||
|
|
||||||
|
await toolbar.openFeatureTreePane()
|
||||||
|
await toolbar.openPane('files')
|
||||||
|
|
||||||
|
await toolbar.openFile('good.kcl')
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
toolbar.featureTreePane.getByRole('button', { name: 'Sketch' })
|
||||||
|
).toHaveCount(2)
|
||||||
|
|
||||||
|
await toolbar.openFile('error.kcl')
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
toolbar.featureTreePane.getByRole('button', { name: 'Sketch' })
|
||||||
|
).toHaveCount(0)
|
||||||
|
})
|
||||||
|
|
||||||
test('adding a syntax error, recovers after fixing', async ({
|
test('adding a syntax error, recovers after fixing', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
|
|
||||||
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
import type { CmdBarFixture } from '@e2e/playwright/fixtures/cmdBarFixture'
|
||||||
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
import type { SceneFixture } from '@e2e/playwright/fixtures/sceneFixture'
|
||||||
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
import { TEST_SETTINGS, TEST_SETTINGS_KEY } from '@e2e/playwright/storageStates'
|
||||||
@ -9,6 +8,7 @@ import {
|
|||||||
settingsToToml,
|
settingsToToml,
|
||||||
} from '@e2e/playwright/test-utils'
|
} from '@e2e/playwright/test-utils'
|
||||||
import { expect, test } from '@e2e/playwright/zoo-test'
|
import { expect, test } from '@e2e/playwright/zoo-test'
|
||||||
|
import { KCL_DEFAULT_LENGTH } from '@src/lib/constants'
|
||||||
|
|
||||||
test.beforeEach(async ({ page, context }) => {
|
test.beforeEach(async ({ page, context }) => {
|
||||||
// Make the user avatar image always 404
|
// Make the user avatar image always 404
|
||||||
@ -766,7 +766,7 @@ test.describe('Grid visibility', { tag: '@snapshot' }, () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('theme persists', async ({ page, context }) => {
|
test('theme persists', async ({ page, context, homePage }) => {
|
||||||
const u = await getUtils(page)
|
const u = await getUtils(page)
|
||||||
await context.addInitScript(async () => {
|
await context.addInitScript(async () => {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
@ -784,7 +784,7 @@ test('theme persists', async ({ page, context }) => {
|
|||||||
|
|
||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
await u.waitForAuthSkipAppStart()
|
await homePage.goToModelingScene()
|
||||||
await page.waitForTimeout(500)
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
// await page.getByRole('link', { name: 'Settings Settings (tooltip)' }).click()
|
// await page.getByRole('link', { name: 'Settings Settings (tooltip)' }).click()
|
||||||
@ -812,7 +812,7 @@ test('theme persists', async ({ page, context }) => {
|
|||||||
// Disconnect and reconnect to check the theme persists through a reload
|
// Disconnect and reconnect to check the theme persists through a reload
|
||||||
|
|
||||||
// Expect the network to be down
|
// Expect the network to be down
|
||||||
await expect(networkToggle).toContainText('Offline')
|
await expect(networkToggle).toContainText('Problem')
|
||||||
|
|
||||||
// simulate network up
|
// simulate network up
|
||||||
await u.emulateNetworkConditions({
|
await u.emulateNetworkConditions({
|
||||||
@ -873,6 +873,50 @@ sweepSketch = startSketchOn(XY)
|
|||||||
mask: lowerRightMasks(page),
|
mask: lowerRightMasks(page),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
test('code color goober works with single quotes', async ({
|
||||||
|
page,
|
||||||
|
context,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
}) => {
|
||||||
|
const u = await getUtils(page)
|
||||||
|
await context.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`// Create a pipe using a sweep.
|
||||||
|
|
||||||
|
// Create a path for the sweep.
|
||||||
|
sweepPath = startSketchOn(XZ)
|
||||||
|
|> startProfile(at = [0.05, 0.05])
|
||||||
|
|> line(end = [0, 7])
|
||||||
|
|> tangentialArc(angle = 90, radius = 5)
|
||||||
|
|> line(end = [-3, 0])
|
||||||
|
|> tangentialArc(angle = -90, radius = 5)
|
||||||
|
|> line(end = [0, 7])
|
||||||
|
|
||||||
|
sweepSketch = startSketchOn(XY)
|
||||||
|
|> startProfile(at = [2, 0])
|
||||||
|
|> arc(angleStart = 0, angleEnd = 360, radius = 2)
|
||||||
|
|> sweep(path = sweepPath)
|
||||||
|
|> appearance(
|
||||||
|
color = '#bb00ff',
|
||||||
|
metalness = 90,
|
||||||
|
roughness = 90
|
||||||
|
)
|
||||||
|
`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await page.setViewportSize({ width: 1200, height: 1000 })
|
||||||
|
await u.waitForAuthSkipAppStart()
|
||||||
|
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await expect(page, 'expect small color widget').toHaveScreenshot({
|
||||||
|
maxDiffPixels: 100,
|
||||||
|
mask: lowerRightMasks(page),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test('code color goober opening window', async ({
|
test('code color goober opening window', async ({
|
||||||
page,
|
page,
|
||||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 66 KiB |