-
Notifications
You must be signed in to change notification settings - Fork 0
feat(ci): optimize release workflow for dual registry publishing #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
9347969
feat(ci): optimize release workflow for dual registry publishing
Mearman 1360c74
feat(ci): add reusable composite actions for release workflow
Mearman 08fd0b1
feat(build): enable incremental TypeScript builds with caching
Mearman 267f487
docs(ci): add release workflow documentation with Mermaid diagrams
Mearman 2646d4f
chore: update gitignore with TypeScript build artifacts
Mearman a9577c0
fix(ci): implement proper OIDC authentication in composite action
Mearman 2327908
fix(ci): resolve workflow dependencies and race conditions
Mearman 753c2c5
fix(ci): ensure GitHub Packages uses version-bumped package.json
Mearman 1676de4
fix(ci): add lint gating for publishing and remove unused install job
Mearman File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| # Release Workflow | ||
|
|
||
| Publishes Sapatos to GitHub Packages and npmjs with OIDC authentication. | ||
|
|
||
| ## Workflow Flow | ||
|
|
||
| ```mermaid | ||
| graph TD | ||
| A[version-bump<br/>local version bump] --> B[install] | ||
| A --> C[lint] | ||
| A --> D[build] | ||
| A --> E[configure-npmjs] | ||
| D --> E | ||
| D --> F[publish-gh] | ||
| E --> G[build-npmjs] | ||
| G --> H[publish-npmjs] | ||
| F --> I[create-release<br/>tag original commit] | ||
| H --> I | ||
| I --> J[push-changes<br/>commit updates] | ||
|
|
||
| style A fill:#e1f5fe | ||
| style D fill:#fff3e0 | ||
| style E fill:#fff3e0 | ||
| style G fill:#fff3e0 | ||
| style I fill:#f3e5f5,stroke-dasharray: 5 5 | ||
| style J fill:#e8f5e8 | ||
| ``` | ||
|
|
||
| ## Job Dependencies | ||
|
|
||
| - `version-bump` → `lint`, `build`, `configure-npmjs` | ||
| - `build` → `configure-npmjs` → `build-npmjs` | ||
| - `lint` and `build` → `publish-gh` (must pass for publishing) | ||
| - `build-npmjs` → `publish-npmjs` (npmjs) | ||
| - `publish-gh`, `publish-npmjs`, `version-bump` → `create-release` (tag original commit) | ||
| - `create-release` → `push-changes` (commit version updates) | ||
|
|
||
| ### Parallel Execution | ||
| - `lint` runs parallel with build and configure-npmjs | ||
| - `publish-gh` waits for both lint and build to pass | ||
| - `publish-gh` runs parallel with npmjs build chain | ||
| - TypeScript cache shared between builds | ||
|
|
||
| ## Artifact Flow | ||
|
|
||
| ```mermaid | ||
| graph LR | ||
| subgraph "Build & Cache" | ||
| A1[version-bump<br/>local version bump<br/>uploads release-files] | ||
| A1 --> C1[lint] | ||
| A1 --> D1[build] --> E1[TypeScript cache + dist-files] | ||
| F1[configure-npmjs<br/>removes publishConfig] | ||
| A1 --> F1 | ||
| D1 --> F1 | ||
| F1 --> G1[build-npmjs] --> H1[TypeScript cache + dist-files-npmjs] | ||
| D1 -.->|cache share| G1 | ||
| end | ||
|
|
||
| subgraph "Publishing" | ||
| E1 --> I1[publish-gh<br/>GitHub Packages] | ||
| H1 --> J1[publish-npmjs<br/>npmjs + OIDC] | ||
| A1 --> K1[create-release<br/>tag original commit] | ||
| I1 --> K1 | ||
| J1 --> K1 | ||
| A1 --> L1[push-changes<br/>commit version updates] | ||
| K1 --> L1 | ||
| end | ||
|
|
||
| subgraph "Cache Storage" | ||
| M1[GitHub Actions Cache<br/>node_modules + .tsbuildinfo + dist/] | ||
| E1 -.->|stores| M1 | ||
| G1 -.->|uses| M1 | ||
| E1 -.->|uses| M1 | ||
| end | ||
|
|
||
| style A1 fill:#e1f5fe | ||
| style D1 fill:#fff3e0 | ||
| style G1 fill:#fff3e0 | ||
| style K1 fill:#f3e5f5,stroke-dasharray: 5 5 | ||
| style L1 fill:#e8f5e8 | ||
| style M1 fill:#e8f5e8,stroke-dasharray: 3 3 | ||
| style I1 fill:#f3e5f5 | ||
| style J1 fill:#f3e5f5 | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| **Actions** → **Manual Release** → Select release type → **Run workflow** | ||
|
|
||
| Optional dry run mode available. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| name: 'Build Project with Caching' | ||
| description: 'Builds the project with TypeScript cache and compressed artifacts' | ||
|
|
||
| inputs: | ||
| upload-artifacts: | ||
| description: 'Whether to upload build artifacts' | ||
| required: false | ||
| default: 'true' | ||
| artifact-name: | ||
| description: 'Name for the build artifacts' | ||
| required: false | ||
| default: 'dist-files' | ||
| cache-key-suffix: | ||
| description: 'Additional suffix for cache key' | ||
| required: false | ||
| default: '' | ||
| use-ts-cache: | ||
| description: 'Whether to use TypeScript build cache' | ||
| required: false | ||
| default: 'true' | ||
|
|
||
|
|
||
| runs: | ||
| using: 'composite' | ||
| steps: | ||
| - name: Setup Node.js with dependencies | ||
| uses: ./.github/actions/node-setup | ||
|
|
||
| - name: Cache TypeScript build | ||
| id: ts-cache | ||
| if: inputs.use-ts-cache == 'true' | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| .tsbuildinfo | ||
| dist/ | ||
| key: ${{ runner.os }}-ts-build-v${{ inputs.cache-key-suffix }}-${{ hashFiles('**/src/**/*.ts', '**/tsconfig*.json', 'package.json') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-ts-build-v${{ inputs.cache-key-suffix }}- | ||
| ${{ runner.os }}-ts-build- | ||
|
|
||
| - name: Build project | ||
| shell: bash | ||
| run: | | ||
| if [ "${{ steps.ts-cache.outputs.cache-hit }}" == "true" ]; then | ||
| echo "TypeScript cache hit! Skipping rebuild." | ||
| else | ||
| echo "TypeScript cache miss, building..." | ||
| npm run build | ||
| fi | ||
|
|
||
| - name: Upload build artifacts | ||
| if: inputs.upload-artifacts == 'true' | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: ${{ inputs.artifact-name }} | ||
| path: | | ||
| dist/ | ||
| *.js | ||
| *.mjs | ||
| *.d.ts | ||
| retention-days: 7 |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| name: 'Node.js Setup with Caching' | ||
| description: 'Sets up Node.js and handles dependencies with GitHub Actions cache' | ||
|
|
||
| inputs: | ||
| node-version: | ||
| description: 'Node.js version to use' | ||
| required: false | ||
| default: '22' | ||
| registry-url: | ||
| description: 'Registry URL for npm packages' | ||
| required: false | ||
| scope: | ||
| description: 'npm scope for packages' | ||
| required: false | ||
| cache: | ||
| description: 'Cache npm dependencies' | ||
| required: false | ||
| default: 'true' | ||
| install-dependencies: | ||
| description: 'Whether to install dependencies' | ||
| required: false | ||
| default: 'true' | ||
| cache-dependency-path: | ||
| description: 'Path to dependency file for cache key' | ||
| required: false | ||
| default: 'package-lock.json' | ||
|
|
||
| outputs: | ||
| node-version: | ||
| description: 'The Node.js version that was set up' | ||
| value: ${{ steps.setup-node.outputs.node-version }} | ||
| cache-hit: | ||
| description: 'Whether the cache was hit' | ||
| value: ${{ steps.cache.outputs.cache-hit }} | ||
|
|
||
| runs: | ||
| using: 'composite' | ||
| steps: | ||
| - name: Setup Node.js | ||
| id: setup-node | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| node-version: ${{ inputs.node-version }} | ||
| registry-url: ${{ inputs.registry-url }} | ||
| scope: ${{ inputs.scope }} | ||
|
|
||
| - name: Cache dependencies | ||
| id: cache | ||
| if: inputs.cache == 'true' | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: | | ||
| ~/.npm | ||
| node_modules | ||
| key: ${{ runner.os }}-node-v${{ inputs.node-version }}-${{ hashFiles(inputs.cache-dependency-path) }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-node-v${{ inputs.node-version }}- | ||
| ${{ runner.os }}-node- | ||
|
|
||
| - name: Install dependencies | ||
| if: inputs.install-dependencies == 'true' | ||
| shell: bash | ||
| run: npm ci --prefer-offline --no-audit --no-fund | ||
|
|
||
|
|
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| name: 'Publish Package to Registry' | ||
| description: 'Publishes package to specified npm registry with enhanced OIDC and artifact support' | ||
|
|
||
| inputs: | ||
| registry: | ||
| description: 'Registry to publish to (gh or npmjs)' | ||
| required: true | ||
| download-artifacts: | ||
| description: 'Whether to download build artifacts' | ||
| required: false | ||
| default: 'true' | ||
| remove-publish-config: | ||
| description: 'Whether to remove publishConfig before publishing' | ||
| required: false | ||
| default: 'false' | ||
| publish-flags: | ||
| description: 'Additional flags for npm publish' | ||
| required: false | ||
| default: '--access public' | ||
| use-oidc: | ||
| description: 'Whether to use OIDC for authentication' | ||
| required: false | ||
| default: 'auto' | ||
| auth-token: | ||
| description: 'Authentication token for registry' | ||
| required: false | ||
|
|
||
| runs: | ||
| using: 'composite' | ||
| steps: | ||
| - name: Download release files with version info | ||
| if: inputs.download-artifacts == 'true' | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: release-files | ||
|
|
||
| - name: Download and extract build artifacts | ||
| if: inputs.download-artifacts == 'true' | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: ${{ inputs.registry == 'npmjs' && 'dist-files-npmjs' || 'dist-files' }} | ||
|
|
||
| - name: Download npmjs package config | ||
| if: inputs.registry == 'npmjs' | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: npmjs-package-config | ||
|
|
||
| - name: Setup Node.js for ${{ inputs.registry }} | ||
| uses: ./.github/actions/node-setup | ||
| with: | ||
| registry-url: ${{ inputs.registry == 'gh' && 'https://npm.pkg.github.com' || 'https://registry.npmjs.org' }} | ||
| scope: ${{ inputs.registry == 'gh' && '@architect-eng' || '' }} | ||
| install-dependencies: 'false' | ||
|
|
||
| - name: Remove publishConfig for npmjs | ||
| if: inputs.remove-publish-config == 'true' | ||
| shell: bash | ||
| run: npm pkg delete publishConfig | ||
|
|
||
| - name: Determine OIDC usage | ||
| id: oidc-config | ||
| shell: bash | ||
| run: | | ||
| USE_OIDC="${{ inputs.use-oidc }}" | ||
| if [[ "$USE_OIDC" == "auto" ]]; then | ||
| USE_OIDC="${{ inputs.registry == 'npmjs' && 'true' || 'false' }}" | ||
| fi | ||
| echo "use-oidc=$USE_OIDC" >> $GITHUB_OUTPUT | ||
| echo "OIDC will be used: $USE_OIDC" | ||
|
|
||
| - name: Get OIDC token for npm | ||
| id: oidc-token | ||
| if: steps.oidc-config.outputs.use-oidc == 'true' | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const token = await core.getIDToken('npm'); | ||
| core.setOutput('token', token); | ||
|
|
||
| - name: Publish to ${{ inputs.registry }} | ||
| shell: bash | ||
| run: | | ||
| PUBLISH_FLAGS="${{ inputs.publish-flags }}" | ||
| USE_OIDC="${{ steps.oidc-config.outputs.use-oidc }}" | ||
|
|
||
| if [[ "$USE_OIDC" == "true" ]]; then | ||
| PUBLISH_FLAGS="$PUBLISH_FLAGS --provenance" | ||
| export NODE_AUTH_TOKEN="${{ steps.oidc-token.outputs.token }}" | ||
| echo "Publishing with OIDC authentication and provenance" | ||
| else | ||
| export NODE_AUTH_TOKEN="${{ inputs.auth-token }}" | ||
| echo "Publishing with token authentication" | ||
| fi | ||
|
|
||
| echo "Publish flags: $PUBLISH_FLAGS" | ||
| npm publish $PUBLISH_FLAGS | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.