first commit
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
name: Set up dependencies
|
||||
description: >-
|
||||
Set up Python and Node.js with dependency caching, then install the repo
|
||||
Python and Node dependencies used by tests and production bundling.
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: pip
|
||||
cache-dependency-path: requirements-dev.txt
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
cache-dependency-path: |
|
||||
packages/cadjs/package-lock.json
|
||||
packages/implicitjs/package-lock.json
|
||||
viewer/package-lock.json
|
||||
docs/package-lock.json
|
||||
|
||||
- name: Install Python dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install -r requirements-dev.txt
|
||||
|
||||
- name: Install Node dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
npm ci --prefix packages/cadjs
|
||||
npm ci --prefix packages/implicitjs
|
||||
npm ci --prefix viewer
|
||||
npm ci --prefix docs
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
changelog:
|
||||
exclude:
|
||||
labels:
|
||||
- ignore-for-release
|
||||
authors:
|
||||
- github-actions[bot]
|
||||
categories:
|
||||
- title: Breaking Changes
|
||||
labels:
|
||||
- breaking-change
|
||||
- semver-major
|
||||
- title: Features
|
||||
labels:
|
||||
- enhancement
|
||||
- feature
|
||||
- semver-minor
|
||||
- title: Fixes
|
||||
labels:
|
||||
- bug
|
||||
- fix
|
||||
- semver-patch
|
||||
- title: Maintenance
|
||||
labels:
|
||||
- dependencies
|
||||
- documentation
|
||||
- maintenance
|
||||
- title: Other Changes
|
||||
labels:
|
||||
- "*"
|
||||
@@ -0,0 +1,60 @@
|
||||
name: Deploy Docs
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: Production-layout ref to deploy, normally main or a publish commit.
|
||||
required: true
|
||||
default: main
|
||||
type: string
|
||||
workflow_call:
|
||||
inputs:
|
||||
ref:
|
||||
description: Production-layout ref to deploy.
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: deploy-docs
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy docs app
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out deploy ref
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.ref }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Install Vercel CLI
|
||||
run: npm install --global vercel@50.28.0
|
||||
|
||||
- name: Deploy docs app to Vercel production
|
||||
env:
|
||||
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
||||
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
||||
VERCEL_DOCS_PROJECT_ID: ${{ secrets.VERCEL_DOCS_PROJECT_ID }}
|
||||
run: |
|
||||
for name in VERCEL_TOKEN VERCEL_ORG_ID VERCEL_DOCS_PROJECT_ID; do
|
||||
if [ -z "${!name:-}" ]; then
|
||||
echo "Missing GitHub Actions secret: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
scripts/github-workflows/deploy-vercel-app.sh \
|
||||
--label "Docs app" \
|
||||
--project-id "$VERCEL_DOCS_PROJECT_ID" \
|
||||
--public-urls "https://www.cadskills.xyz https://cadskills.xyz https://www.cad.fun https://cad.fun"
|
||||
@@ -0,0 +1,60 @@
|
||||
name: Deploy Viewer
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: Production-layout ref to deploy, normally main or a publish commit.
|
||||
required: true
|
||||
default: main
|
||||
type: string
|
||||
workflow_call:
|
||||
inputs:
|
||||
ref:
|
||||
description: Production-layout ref to deploy.
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: deploy-viewer
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy demo viewer app
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out deploy ref
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.ref }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Install Vercel CLI
|
||||
run: npm install --global vercel@50.28.0
|
||||
|
||||
- name: Deploy demo viewer app to Vercel production
|
||||
env:
|
||||
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
||||
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
||||
VERCEL_VIEWER_PROJECT_ID: ${{ secrets.VERCEL_VIEWER_PROJECT_ID }}
|
||||
run: |
|
||||
for name in VERCEL_TOKEN VERCEL_ORG_ID VERCEL_VIEWER_PROJECT_ID; do
|
||||
if [ -z "${!name:-}" ]; then
|
||||
echo "Missing GitHub Actions secret: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
scripts/github-workflows/deploy-vercel-app.sh \
|
||||
--label "Demo viewer app" \
|
||||
--project-id "$VERCEL_VIEWER_PROJECT_ID" \
|
||||
--public-urls "https://demo.cadskills.xyz https://demo.cad.fun"
|
||||
+512
@@ -0,0 +1,512 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
bump:
|
||||
description: Semver part to bump when set_version is empty.
|
||||
required: true
|
||||
default: patch
|
||||
type: choice
|
||||
options:
|
||||
- patch
|
||||
- minor
|
||||
- major
|
||||
set_version:
|
||||
description: Exact X.Y.Z version to release instead of bumping. Set to the current version to resume a failed publish.
|
||||
required: false
|
||||
type: string
|
||||
base_branch:
|
||||
description: Branch to release from and merge the release PR into.
|
||||
required: true
|
||||
default: develop
|
||||
type: string
|
||||
target_branch:
|
||||
description: Publish target. Use main for releases; use build-test only to test CI/CD or build changes.
|
||||
required: true
|
||||
default: main
|
||||
type: choice
|
||||
options:
|
||||
- main
|
||||
- build-test
|
||||
dry_run:
|
||||
description: Show the release version changes without pushing, merging, or publishing.
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
publish:
|
||||
description: Publish the GitHub Release. Set to false to leave it as a draft.
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
create_release:
|
||||
description: Create the GitHub Release after pushing the tag.
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
auto_merge:
|
||||
description: Merge the release PR immediately, then publish. Set to false to only prepare the PR.
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
group: release-${{ inputs.base_branch }}-${{ inputs.target_branch }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
release-pr:
|
||||
name: Release PR
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
source_sha: ${{ steps.publish_source.outputs.sha }}
|
||||
|
||||
steps:
|
||||
- name: Check out base branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.base_branch }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Configure release credentials
|
||||
env:
|
||||
RELEASE_ORCHESTRATOR_TOKEN: ${{ secrets.RELEASE_ORCHESTRATOR_TOKEN }}
|
||||
PREPARE_RELEASE_TOKEN: ${{ secrets.PREPARE_RELEASE_TOKEN }}
|
||||
PUBLISH_PUSH_TOKEN: ${{ secrets.PUBLISH_PUSH_TOKEN }}
|
||||
BUILD_TEST_PUSH_TOKEN: ${{ secrets.BUILD_TEST_PUSH_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
release_token="${RELEASE_ORCHESTRATOR_TOKEN:-${PREPARE_RELEASE_TOKEN:-${PUBLISH_PUSH_TOKEN:-${BUILD_TEST_PUSH_TOKEN:-$GITHUB_TOKEN}}}}"
|
||||
if [ -n "${RELEASE_ORCHESTRATOR_TOKEN:-}" ]; then
|
||||
echo "Using RELEASE_ORCHESTRATOR_TOKEN for release orchestration."
|
||||
elif [ -n "${PREPARE_RELEASE_TOKEN:-}" ]; then
|
||||
echo "Using PREPARE_RELEASE_TOKEN for release orchestration."
|
||||
elif [ -n "${PUBLISH_PUSH_TOKEN:-}" ]; then
|
||||
echo "Using PUBLISH_PUSH_TOKEN for release orchestration."
|
||||
elif [ -n "${BUILD_TEST_PUSH_TOKEN:-}" ]; then
|
||||
echo "Using BUILD_TEST_PUSH_TOKEN for release orchestration."
|
||||
else
|
||||
echo "Using GITHUB_TOKEN for release orchestration."
|
||||
fi
|
||||
|
||||
git remote set-url origin "https://x-access-token:${release_token}@github.com/${GITHUB_REPOSITORY}.git"
|
||||
{
|
||||
echo "GH_TOKEN=$release_token"
|
||||
echo "RELEASE_TOKEN=$release_token"
|
||||
} >> "$GITHUB_ENV"
|
||||
|
||||
- name: Prepare canonical version
|
||||
id: version
|
||||
env:
|
||||
BUMP: ${{ inputs.bump }}
|
||||
SET_VERSION: ${{ inputs.set_version }}
|
||||
run: |
|
||||
if [ -n "$SET_VERSION" ]; then
|
||||
scripts/release/bump-version.sh --set-version "$SET_VERSION" --no-commit
|
||||
else
|
||||
scripts/release/bump-version.sh "$BUMP" --no-commit
|
||||
fi
|
||||
node scripts/release/sync-version.mjs
|
||||
version="$(tr -d '[:space:]' < plugins/cad/VERSION)"
|
||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||
if git diff --quiet; then
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Base branch already contains release version $version; skipping the release PR."
|
||||
else
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Prepared release version: $version"
|
||||
fi
|
||||
|
||||
- name: Check release version metadata
|
||||
env:
|
||||
CHANGED: ${{ steps.version.outputs.changed }}
|
||||
run: |
|
||||
node scripts/release/sync-version.mjs --check
|
||||
if [ "$CHANGED" = "true" ]; then
|
||||
scripts/release/check-version.sh --incremented-from origin/main
|
||||
latest_tag="$(git tag --list '[0-9]*.[0-9]*.[0-9]*' --sort=-version:refname | head -n 1 || true)"
|
||||
if [ -n "$latest_tag" ]; then
|
||||
scripts/release/check-version.sh --incremented-from "refs/tags/$latest_tag"
|
||||
fi
|
||||
else
|
||||
scripts/release/check-version.sh
|
||||
echo "No version metadata changes; the publish gate decides whether this version still needs to ship."
|
||||
fi
|
||||
|
||||
- name: Check development symlink layout
|
||||
run: scripts/dev/setup-symlinks.sh --check
|
||||
|
||||
- name: Show dry-run diff
|
||||
if: inputs.dry_run
|
||||
run: |
|
||||
git diff --stat
|
||||
git diff -- plugins/cad/VERSION
|
||||
|
||||
- name: Stop after dry run
|
||||
if: inputs.dry_run
|
||||
run: echo "Dry run requested; skipping release branch, PR merge, and publish."
|
||||
|
||||
- name: Create or update release pull request
|
||||
if: ${{ !inputs.dry_run && steps.version.outputs.changed == 'true' }}
|
||||
id: release_pr
|
||||
env:
|
||||
BASE_BRANCH: ${{ inputs.base_branch }}
|
||||
VERSION: ${{ steps.version.outputs.version }}
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
branch="release/$VERSION"
|
||||
body="Bumps plugins/cad/VERSION and derived package/plugin metadata to $VERSION. This PR was created by the one-button Release workflow, which merges it into $BASE_BRANCH immediately; the publish job revalidates the full production bundle before anything ships to the target branch."
|
||||
|
||||
git checkout -B "$branch"
|
||||
git add -A
|
||||
git commit -m "Release $VERSION"
|
||||
git push --force-with-lease origin "$branch"
|
||||
|
||||
if pr_json="$(gh pr view "$branch" --repo "$GITHUB_REPOSITORY" --json number,url 2>/dev/null)"; then
|
||||
pr_number="$(printf '%s\n' "$pr_json" | jq -r '.number')"
|
||||
pr_url="$(printf '%s\n' "$pr_json" | jq -r '.url')"
|
||||
gh pr edit "$pr_number" \
|
||||
--repo "$GITHUB_REPOSITORY" \
|
||||
--base "$BASE_BRANCH" \
|
||||
--title "Release $VERSION" \
|
||||
--body "$body"
|
||||
else
|
||||
pr_url="$(gh pr create \
|
||||
--repo "$GITHUB_REPOSITORY" \
|
||||
--base "$BASE_BRANCH" \
|
||||
--head "$branch" \
|
||||
--title "Release $VERSION" \
|
||||
--body "$body")"
|
||||
pr_number="$(gh pr view "$pr_url" --repo "$GITHUB_REPOSITORY" --json number --jq '.number')"
|
||||
fi
|
||||
|
||||
echo "created=true" >> "$GITHUB_OUTPUT"
|
||||
echo "number=$pr_number" >> "$GITHUB_OUTPUT"
|
||||
echo "url=$pr_url" >> "$GITHUB_OUTPUT"
|
||||
echo "Release PR: $pr_url"
|
||||
|
||||
- name: Merge release pull request
|
||||
if: ${{ !inputs.dry_run && inputs.auto_merge && steps.release_pr.outputs.created == 'true' }}
|
||||
env:
|
||||
PR_NUMBER: ${{ steps.release_pr.outputs.number }}
|
||||
run: |
|
||||
pr_json="$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json headRefOid)"
|
||||
head_sha="$(printf '%s\n' "$pr_json" | jq -r '.headRefOid')"
|
||||
merged=false
|
||||
for attempt in $(seq 1 6); do
|
||||
if gh api \
|
||||
--method PUT \
|
||||
"repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/merge" \
|
||||
-f merge_method=merge \
|
||||
-f sha="$head_sha"; then
|
||||
merged=true
|
||||
break
|
||||
fi
|
||||
echo "Merge attempt $attempt failed; retrying while GitHub computes mergeability..."
|
||||
sleep 10
|
||||
done
|
||||
if [ "$merged" != "true" ]; then
|
||||
echo "Could not merge release PR #$PR_NUMBER." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Stop before publish when auto-merge is disabled
|
||||
if: ${{ !inputs.dry_run && !inputs.auto_merge }}
|
||||
run: echo "auto_merge=false; the release PR was prepared but the publish jobs were skipped."
|
||||
|
||||
- name: Resolve publish source
|
||||
if: ${{ !inputs.dry_run && inputs.auto_merge }}
|
||||
id: publish_source
|
||||
env:
|
||||
BASE_BRANCH: ${{ inputs.base_branch }}
|
||||
run: |
|
||||
git fetch --no-tags origin "+$BASE_BRANCH:refs/remotes/origin/$BASE_BRANCH"
|
||||
source_sha="$(git rev-parse "origin/$BASE_BRANCH^{commit}")"
|
||||
echo "sha=$source_sha" >> "$GITHUB_OUTPUT"
|
||||
echo "Publishing $BASE_BRANCH at $source_sha."
|
||||
|
||||
publish:
|
||||
name: Publish
|
||||
needs: release-pr
|
||||
if: ${{ !inputs.dry_run && inputs.auto_merge }}
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
published: ${{ steps.push.outputs.published }}
|
||||
publish_sha: ${{ steps.commit.outputs.publish_sha }}
|
||||
|
||||
steps:
|
||||
- name: Check out publish source
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.release-pr.outputs.source_sha }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Configure publish credentials
|
||||
env:
|
||||
PUBLISH_PUSH_TOKEN: ${{ secrets.PUBLISH_PUSH_TOKEN }}
|
||||
BUILD_TEST_PUSH_TOKEN: ${{ secrets.BUILD_TEST_PUSH_TOKEN }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if [ -n "$PUBLISH_PUSH_TOKEN" ]; then
|
||||
git remote set-url origin "https://x-access-token:${PUBLISH_PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
|
||||
echo "Using PUBLISH_PUSH_TOKEN for publish push."
|
||||
elif [ -n "$BUILD_TEST_PUSH_TOKEN" ]; then
|
||||
git remote set-url origin "https://x-access-token:${BUILD_TEST_PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
|
||||
echo "Using BUILD_TEST_PUSH_TOKEN for publish push."
|
||||
else
|
||||
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
|
||||
echo "Using GITHUB_TOKEN for publish push."
|
||||
fi
|
||||
|
||||
- name: Check canonical release version
|
||||
run: scripts/release/check-version.sh
|
||||
|
||||
- name: Evaluate release gate
|
||||
id: gate
|
||||
env:
|
||||
BASE_BRANCH: ${{ inputs.base_branch }}
|
||||
TARGET_BRANCH: ${{ inputs.target_branch }}
|
||||
run: |
|
||||
source_sha="$(git rev-parse HEAD)"
|
||||
echo "source_sha=$source_sha" >> "$GITHUB_OUTPUT"
|
||||
|
||||
if [ "$TARGET_BRANCH" != "main" ]; then
|
||||
echo "should_publish=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Build-test publish requested for $source_sha (CI/CD or build testing only)."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$BASE_BRANCH" != "develop" ]; then
|
||||
echo "Real releases must publish develop to main; got base_branch=$BASE_BRANCH." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
current_version="$(tr -d '[:space:]' < plugins/cad/VERSION)"
|
||||
latest_tag="$(git tag --list '[0-9]*.[0-9]*.[0-9]*' --sort=-version:refname | head -n 1 || true)"
|
||||
if ! scripts/release/check-version.sh --incremented-from origin/main >/tmp/publish-main-version-check.log 2>&1; then
|
||||
main_version="$(git show origin/main:plugins/cad/VERSION | tr -d '[:space:]')"
|
||||
if [ "$main_version" = "$current_version" ] && ! git rev-parse --verify --quiet "refs/tags/$current_version" >/dev/null; then
|
||||
echo "Release version already reached origin/main, but tag $current_version is missing; resuming publish."
|
||||
else
|
||||
echo "should_publish=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Skipping publish: version has not advanced past origin/main."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
if [ -n "$latest_tag" ] && ! scripts/release/check-version.sh --incremented-from "refs/tags/$latest_tag" >/tmp/publish-tag-version-check.log 2>&1; then
|
||||
echo "should_publish=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Skipping publish: version has not advanced past latest tag $latest_tag."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "should_publish=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Release version advanced; publishing $source_sha to $TARGET_BRANCH."
|
||||
|
||||
- name: Skip non-release publish
|
||||
if: steps.gate.outputs.should_publish != 'true'
|
||||
run: echo "Publish only updates main when the source version is newer than main and the latest release tag."
|
||||
|
||||
- name: Validate publish target
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
env:
|
||||
SOURCE_SHA: ${{ steps.gate.outputs.source_sha }}
|
||||
TARGET_BRANCH: ${{ inputs.target_branch }}
|
||||
run: |
|
||||
scripts/release/check-publish-source.sh --source-ref "$SOURCE_SHA" --target-ref origin/main
|
||||
if [ "$TARGET_BRANCH" = "main" ]; then
|
||||
echo "Validated main publish target."
|
||||
else
|
||||
echo "Validated build-test target against origin/main."
|
||||
fi
|
||||
|
||||
- name: Set up dependencies
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
uses: ./.github/actions/setup-deps
|
||||
|
||||
- name: Check development symlink layout
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
run: scripts/dev/setup-symlinks.sh --check
|
||||
|
||||
- name: Bundle production outputs
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
run: scripts/bundle/bundle.sh --clean
|
||||
|
||||
- name: Validate production bundle layout
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
run: scripts/github-workflows/check-builds.sh --skip-bundle-check
|
||||
|
||||
- name: Run documentation checks
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
run: scripts/test/test-docs.sh
|
||||
|
||||
- name: Run code tests
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
run: scripts/test/test.sh
|
||||
|
||||
- name: Remove models from publish tree
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
run: |
|
||||
rm -rf models
|
||||
if [ -e models ]; then
|
||||
echo "Failed to remove models from the publish tree." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Commit publish result
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
id: commit
|
||||
env:
|
||||
BASE_BRANCH: ${{ inputs.base_branch }}
|
||||
SOURCE_SHA: ${{ steps.gate.outputs.source_sha }}
|
||||
TARGET_BRANCH: ${{ inputs.target_branch }}
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git add -A
|
||||
if [ -n "$(git ls-files -- models)" ]; then
|
||||
echo "models/ must not be present in the publish commit." >&2
|
||||
git ls-files -- models >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
version="$(tr -d '[:space:]' < plugins/cad/VERSION)"
|
||||
if target_base_sha="$(git rev-parse --verify "origin/$TARGET_BRANCH^{commit}" 2>/dev/null)"; then
|
||||
echo "Using existing $TARGET_BRANCH as publish parent: $target_base_sha"
|
||||
else
|
||||
target_base_sha="$(git rev-parse --verify "origin/main^{commit}")"
|
||||
echo "Target branch $TARGET_BRANCH does not exist; using origin/main as publish parent: $target_base_sha"
|
||||
fi
|
||||
release_base_sha="$(git rev-parse --verify "origin/main^{commit}")"
|
||||
previous_source_sha="$(scripts/release/check-publish-source.sh --target-ref origin/main --print-previous-source)"
|
||||
included_commits="$(git log --oneline --no-decorate "$previous_source_sha..$SOURCE_SHA" || true)"
|
||||
|
||||
message_file="$(mktemp)"
|
||||
{
|
||||
echo "Publish $version from $BASE_BRANCH to $TARGET_BRANCH"
|
||||
echo
|
||||
echo "Source ref: $BASE_BRANCH"
|
||||
echo "Source commit: $SOURCE_SHA"
|
||||
echo "Target branch: $TARGET_BRANCH"
|
||||
echo "Previous target: $target_base_sha"
|
||||
echo "Release base: $release_base_sha"
|
||||
echo "Previous source: $previous_source_sha"
|
||||
echo
|
||||
echo "Included commits since previous source:"
|
||||
if [ -n "$included_commits" ]; then
|
||||
echo "$included_commits"
|
||||
else
|
||||
echo "(no source commits beyond previous published source)"
|
||||
fi
|
||||
} > "$message_file"
|
||||
|
||||
tree_sha="$(git write-tree)"
|
||||
commit_parents=(-p "$target_base_sha")
|
||||
if [ "$SOURCE_SHA" != "$target_base_sha" ]; then
|
||||
commit_parents+=(-p "$SOURCE_SHA")
|
||||
fi
|
||||
publish_commit="$(git commit-tree "$tree_sha" "${commit_parents[@]}" -F "$message_file")"
|
||||
git reset --hard "$publish_commit"
|
||||
echo "publish_sha=$publish_commit" >> "$GITHUB_OUTPUT"
|
||||
echo "Created publish commit: $publish_commit"
|
||||
|
||||
- name: Push target branch
|
||||
if: steps.gate.outputs.should_publish == 'true'
|
||||
id: push
|
||||
env:
|
||||
TARGET_BRANCH: ${{ inputs.target_branch }}
|
||||
run: |
|
||||
if [ "$TARGET_BRANCH" = "main" ]; then
|
||||
git push origin HEAD:main
|
||||
else
|
||||
git push --force-with-lease origin "HEAD:$TARGET_BRANCH"
|
||||
fi
|
||||
echo "published=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
upload-models:
|
||||
name: Upload Models
|
||||
needs:
|
||||
- release-pr
|
||||
- publish
|
||||
if: ${{ needs.publish.outputs.published == 'true' && inputs.target_branch == 'main' }}
|
||||
uses: ./.github/workflows/upload-models.yml
|
||||
with:
|
||||
ref: ${{ needs.release-pr.outputs.source_sha }}
|
||||
secrets: inherit
|
||||
|
||||
deploy-docs:
|
||||
name: Deploy Docs
|
||||
needs: publish
|
||||
if: ${{ needs.publish.outputs.published == 'true' && inputs.target_branch == 'main' }}
|
||||
uses: ./.github/workflows/deploy-docs.yml
|
||||
with:
|
||||
ref: ${{ needs.publish.outputs.publish_sha }}
|
||||
secrets: inherit
|
||||
|
||||
deploy-viewer:
|
||||
name: Deploy Viewer
|
||||
needs: publish
|
||||
if: ${{ needs.publish.outputs.published == 'true' && inputs.target_branch == 'main' }}
|
||||
uses: ./.github/workflows/deploy-viewer.yml
|
||||
with:
|
||||
ref: ${{ needs.publish.outputs.publish_sha }}
|
||||
secrets: inherit
|
||||
|
||||
tag-release:
|
||||
name: Tag and GitHub Release
|
||||
needs:
|
||||
- publish
|
||||
- upload-models
|
||||
- deploy-docs
|
||||
- deploy-viewer
|
||||
if: ${{ needs.publish.outputs.published == 'true' && inputs.target_branch == 'main' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out publish commit
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.publish.outputs.publish_sha }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Configure tag push credentials
|
||||
env:
|
||||
PUBLISH_PUSH_TOKEN: ${{ secrets.PUBLISH_PUSH_TOKEN }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
if [ -n "$PUBLISH_PUSH_TOKEN" ]; then
|
||||
git remote set-url origin "https://x-access-token:${PUBLISH_PUSH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
|
||||
echo "Using PUBLISH_PUSH_TOKEN for tag push."
|
||||
else
|
||||
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
|
||||
echo "Using GITHUB_TOKEN for tag push."
|
||||
fi
|
||||
|
||||
- name: Create release tag and GitHub Release
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
INPUT_PUBLISH: ${{ inputs.publish }}
|
||||
INPUT_CREATE_RELEASE: ${{ inputs.create_release }}
|
||||
run: |
|
||||
args=(--target HEAD)
|
||||
if [ "$INPUT_PUBLISH" = "true" ]; then
|
||||
args+=(--publish)
|
||||
fi
|
||||
if [ "$INPUT_CREATE_RELEASE" != "true" ]; then
|
||||
args+=(--skip-release)
|
||||
fi
|
||||
scripts/release/publish-github-release.sh "${args[@]}"
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches:
|
||||
- develop
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
|
||||
concurrency:
|
||||
group: test-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
version:
|
||||
name: Version Check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: Check release version
|
||||
run: |
|
||||
scripts/release/check-version.sh
|
||||
node scripts/release/sync-version.mjs --check
|
||||
|
||||
test:
|
||||
name: Test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check development layout
|
||||
run: scripts/github-workflows/check-symlinks.sh
|
||||
|
||||
- name: Set up dependencies
|
||||
uses: ./.github/actions/setup-deps
|
||||
|
||||
- name: Bundle production outputs
|
||||
run: scripts/bundle/bundle.sh --clean
|
||||
|
||||
- name: Check production bundle layout
|
||||
run: scripts/github-workflows/check-builds.sh --skip-bundle-check
|
||||
|
||||
- name: Run documentation checks
|
||||
run: scripts/test/test-docs.sh
|
||||
|
||||
- name: Run code tests
|
||||
run: scripts/test/test.sh
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Upload Models
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: Branch, tag, or SHA to upload models from. Use a source branch; main does not contain models/.
|
||||
required: true
|
||||
default: develop
|
||||
type: string
|
||||
workflow_call:
|
||||
inputs:
|
||||
ref:
|
||||
description: Branch, tag, or SHA to upload models from.
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: upload-models
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
name: Upload models catalog
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check out upload ref
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.ref }}
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
cache: npm
|
||||
cache-dependency-path: viewer/package-lock.json
|
||||
|
||||
- name: Install viewer dependencies
|
||||
run: npm ci --prefix viewer
|
||||
|
||||
- name: Upload viewer models catalog
|
||||
env:
|
||||
VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN: ${{ secrets.VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN }}
|
||||
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
|
||||
run: |
|
||||
if [ ! -d models ]; then
|
||||
echo "No models directory at this ref; upload from a source branch such as develop." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN:-}" ] && [ -z "${BLOB_READ_WRITE_TOKEN:-}" ]; then
|
||||
echo "Missing VIEWER_VERCEL_BLOB_READ_WRITE_TOKEN or BLOB_READ_WRITE_TOKEN secret." >&2
|
||||
exit 1
|
||||
fi
|
||||
scripts/viewer/upload-viewer-models-catalog.sh "$PWD/models" --skip-existing --fetch-missing-lfs
|
||||
Reference in New Issue
Block a user