Release #20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| package: | |
| description: "Package to release" | |
| required: true | |
| type: choice | |
| options: | |
| - core | |
| - viewer | |
| - editor | |
| - mcp | |
| - ifc-converter | |
| - all | |
| bump: | |
| description: "Version bump" | |
| required: true | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| dry-run: | |
| description: "Dry run (no publish)" | |
| required: false | |
| type: boolean | |
| default: false | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| environment: npm | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - uses: oven-sh/setup-bun@v2 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 22 | |
| registry-url: "https://registry.npmjs.org" | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Configure git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| - name: Bump versions and sync inter-package references | |
| run: | | |
| BUMP=${{ inputs.bump }} | |
| TARGET=${{ inputs.package }} | |
| bump_version() { | |
| local v=$1 | |
| IFS='.' read -r MAJ MIN PAT <<< "$v" | |
| if [ "$BUMP" = "major" ]; then MAJ=$((MAJ+1)); MIN=0; PAT=0; fi | |
| if [ "$BUMP" = "minor" ]; then MIN=$((MIN+1)); PAT=0; fi | |
| if [ "$BUMP" = "patch" ]; then PAT=$((PAT+1)); fi | |
| echo "$MAJ.$MIN.$PAT" | |
| } | |
| # Track new versions in shell-local vars. | |
| # NOTE: $GITHUB_ENV writes don't surface within the same step, so the | |
| # peerDeps sync below must use shell vars, not env indirection. | |
| declare -A NEW_VERSIONS | |
| for pkg in core viewer editor mcp ifc-converter; do | |
| if [ "$TARGET" = "$pkg" ] || [ "$TARGET" = "all" ]; then | |
| CUR=$(jq -r '.version' packages/$pkg/package.json) | |
| NEW=$(bump_version "$CUR") | |
| jq --arg v "$NEW" '.version = $v' packages/$pkg/package.json > tmp.json && mv tmp.json packages/$pkg/package.json | |
| NEW_VERSIONS[$pkg]=$NEW | |
| UPPER=$(echo "$pkg" | tr '[:lower:]' '[:upper:]' | tr '-' '_') | |
| # Also export for the publish/commit/tag steps that follow. | |
| echo "${UPPER}_VERSION=$NEW" >> $GITHUB_ENV | |
| echo "Bumped @pascal-app/$pkg: $CUR → $NEW" | |
| fi | |
| done | |
| # Sync inter-package references in peerDependencies and devDependencies. | |
| # Anything that references a bumped @pascal-app/* package is updated to ^NEW. | |
| for pkg in core viewer editor mcp ifc-converter; do | |
| FILE=packages/$pkg/package.json | |
| for dep in core viewer editor mcp ifc-converter; do | |
| VAL="${NEW_VERSIONS[$dep]}" | |
| [ -z "$VAL" ] && continue | |
| jq --arg name "@pascal-app/$dep" --arg v "^$VAL" ' | |
| if .peerDependencies[$name] then .peerDependencies[$name] = $v else . end | |
| | if .devDependencies[$name] then .devDependencies[$name] = $v else . end | |
| ' "$FILE" > tmp.json && mv tmp.json "$FILE" | |
| done | |
| done | |
| echo "=== @pascal-app/* refs after sync ===" | |
| for pkg in core viewer editor mcp ifc-converter; do | |
| echo "--- packages/$pkg/package.json ---" | |
| jq '{ peerDependencies: (.peerDependencies // {} | with_entries(select(.key | startswith("@pascal-app/")))), devDependencies: (.devDependencies // {} | with_entries(select(.key | startswith("@pascal-app/")))) }' packages/$pkg/package.json | |
| done | |
| - name: Build & publish core | |
| if: inputs.package == 'core' || inputs.package == 'all' | |
| working-directory: packages/core | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| bun run build | |
| if [ "${{ inputs.dry-run }}" = "true" ]; then | |
| echo "🏜️ Dry run — would publish @pascal-app/core@$CORE_VERSION" | |
| npm publish --dry-run --access public | |
| else | |
| npm publish --access public | |
| echo "📦 Published @pascal-app/core@$CORE_VERSION" | |
| fi | |
| - name: Build & publish viewer | |
| if: inputs.package == 'viewer' || inputs.package == 'all' | |
| working-directory: packages/viewer | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| bun run build | |
| if [ "${{ inputs.dry-run }}" = "true" ]; then | |
| echo "🏜️ Dry run — would publish @pascal-app/viewer@$VIEWER_VERSION" | |
| npm publish --dry-run --access public | |
| else | |
| npm publish --access public | |
| echo "📦 Published @pascal-app/viewer@$VIEWER_VERSION" | |
| fi | |
| - name: Publish editor | |
| if: inputs.package == 'editor' || inputs.package == 'all' | |
| working-directory: packages/editor | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| if [ "${{ inputs.dry-run }}" = "true" ]; then | |
| echo "🏜️ Dry run — would publish @pascal-app/editor@$EDITOR_VERSION" | |
| npm publish --dry-run --access public | |
| else | |
| npm publish --access public | |
| echo "📦 Published @pascal-app/editor@$EDITOR_VERSION" | |
| fi | |
| - name: Build & publish mcp | |
| if: inputs.package == 'mcp' || inputs.package == 'all' | |
| working-directory: packages/mcp | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| bun run build | |
| if [ "${{ inputs.dry-run }}" = "true" ]; then | |
| echo "🏜️ Dry run — would publish @pascal-app/mcp@$MCP_VERSION" | |
| npm publish --dry-run --access public | |
| else | |
| npm publish --access public | |
| echo "📦 Published @pascal-app/mcp@$MCP_VERSION" | |
| fi | |
| - name: Build & publish ifc-converter | |
| if: inputs.package == 'ifc-converter' || inputs.package == 'all' | |
| working-directory: packages/ifc-converter | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| bun run build | |
| if [ "${{ inputs.dry-run }}" = "true" ]; then | |
| echo "🏜️ Dry run — would publish @pascal-app/ifc-converter@$IFC_CONVERTER_VERSION" | |
| npm publish --dry-run --access public | |
| else | |
| npm publish --access public | |
| echo "📦 Published @pascal-app/ifc-converter@$IFC_CONVERTER_VERSION" | |
| fi | |
| - name: Commit version bumps & tag | |
| if: inputs.dry-run == false | |
| run: | | |
| git add -A | |
| PKGS="" | |
| TAGS="" | |
| if [ -n "$CORE_VERSION" ]; then | |
| PKGS="$PKGS @pascal-app/core@$CORE_VERSION" | |
| TAGS="$TAGS @pascal-app/core@$CORE_VERSION" | |
| fi | |
| if [ -n "$VIEWER_VERSION" ]; then | |
| PKGS="$PKGS @pascal-app/viewer@$VIEWER_VERSION" | |
| TAGS="$TAGS @pascal-app/viewer@$VIEWER_VERSION" | |
| fi | |
| if [ -n "$EDITOR_VERSION" ]; then | |
| PKGS="$PKGS @pascal-app/editor@$EDITOR_VERSION" | |
| TAGS="$TAGS @pascal-app/editor@$EDITOR_VERSION" | |
| fi | |
| if [ -n "$MCP_VERSION" ]; then | |
| PKGS="$PKGS @pascal-app/mcp@$MCP_VERSION" | |
| TAGS="$TAGS @pascal-app/mcp@$MCP_VERSION" | |
| fi | |
| if [ -n "$IFC_CONVERTER_VERSION" ]; then | |
| PKGS="$PKGS @pascal-app/ifc-converter@$IFC_CONVERTER_VERSION" | |
| TAGS="$TAGS @pascal-app/ifc-converter@$IFC_CONVERTER_VERSION" | |
| fi | |
| git commit -m "release:${PKGS}" | |
| for TAG in $TAGS; do | |
| git tag "$TAG" | |
| done | |
| git push --follow-tags |