Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .github/REAMDE.md
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.
62 changes: 62 additions & 0 deletions .github/actions/build/action.yml
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
65 changes: 65 additions & 0 deletions .github/actions/node-setup/action.yml
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


97 changes: 97 additions & 0 deletions .github/actions/publish-package/action.yml
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
Loading