Skip to content
Merged
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
15 changes: 15 additions & 0 deletions .craft.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
minVersion: '2.21.1'
changelog:
policy: auto
versioning:
policy: auto
artifactProvider:
name: github
config:
artifacts:
CI: npm-tarball
targets:
- name: npm
access: public
oidc: true
- name: github
47 changes: 35 additions & 12 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Build & Test

on:
push:
branches: [main]
branches: [main, 'release/**']
pull_request:

concurrency:
Expand All @@ -13,23 +13,18 @@ defaults:
run:
shell: bash

env:
BUILD_CACHE_KEY: ${{ github.sha }}
CACHED_BUILD_PATHS: |
${{ github.workspace }}/packages/*/dist

jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Set up Node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version-file: package.json
cache: npm
Expand All @@ -41,7 +36,7 @@ jobs:
run: npm run build

- name: Store dist
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: dist
if-no-files-found: error
Expand All @@ -57,12 +52,12 @@ jobs:
needs: build
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Set up Node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version-file: package.json
cache: npm
Expand All @@ -71,7 +66,7 @@ jobs:
run: npm install

- name: Download dist
uses: actions/download-artifact@v4
uses: actions/download-artifact@v7
with:
name: dist
path: dist
Expand All @@ -89,3 +84,31 @@ jobs:
expected=$(cat asset.txt)
actual=$(./dist-bin/sample-linux-x64)
[ "$actual" = "$expected" ]

artifacts:
name: Artifacts
if: startsWith(github.ref, 'refs/heads/release/')
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: actions/setup-node@v6
with:
node-version-file: package.json
cache: npm

- run: npm ci

- uses: actions/download-artifact@v7
with:
name: dist
path: dist

- name: Pack tarball
run: npm pack

- uses: actions/upload-artifact@v7
with:
name: npm-tarball
path: '*.tgz'
80 changes: 80 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Publish
on:
issues:
types: [labeled]

jobs:
publish:
if: github.event.label.name == 'accepted' && github.event.issue.state == 'open'
runs-on: ubuntu-latest
name: Publish release
environment: production
permissions:
contents: write
id-token: write
issues: write
timeout-minutes: 15
steps:
- uses: actions/create-github-app-token@v3
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}

- name: Parse publish request
id: inputs
env:
ISSUE_TITLE: ${{ github.event.issue.title }}
run: |
# Title format: "publish: owner/repo@VERSION"
VERSION=$(echo "$ISSUE_TITLE" | grep -oP '@\K[^\s]+$')
if [[ -z "$VERSION" ]]; then
echo "::error::Could not parse version from issue title: $ISSUE_TITLE"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- uses: actions/checkout@v6
with:
ref: release/${{ steps.inputs.outputs.version }}
token: ${{ steps.app-token.outputs.token }}
fetch-depth: 0

- name: Set git user
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

- uses: actions/setup-node@v6
with:
node-version: 24

- name: Install Craft
run: |
CRAFT_URL=$(curl -fsSL https://api.github.com/repos/getsentry/craft/releases/latest \
| jq -r '.assets[] | select(.name == "craft") | .browser_download_url')
sudo curl -fsSL -o /usr/local/bin/craft "$CRAFT_URL"
sudo chmod +x /usr/local/bin/craft

- name: Publish
run: craft publish "${{ steps.inputs.outputs.version }}" --no-input --no-status-check
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}

- name: Close issue on success
if: success()
env:
GH_TOKEN: ${{ github.token }}
run: |
gh issue close "${{ github.event.issue.number }}" \
--comment "Published **${{ steps.inputs.outputs.version }}** successfully.
[Workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"

- name: Comment on failure
if: failure()
env:
GH_TOKEN: ${{ github.token }}
run: |
gh issue comment "${{ github.event.issue.number }}" \
--body "Publish failed. [View workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})"
gh issue edit "${{ github.event.issue.number }}" --remove-label accepted
39 changes: 39 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Release
on:
workflow_dispatch:
inputs:
version:
description: Version to release (or "auto")
required: false
force:
description: Force a release even when there are release-blockers
type: boolean
default: false

jobs:
release:
runs-on: ubuntu-latest
name: Release a new version
environment: production
permissions:
contents: write
issues: write
steps:
- uses: actions/create-github-app-token@v3
id: app-token
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}

- uses: actions/checkout@v6
with:
token: ${{ steps.app-token.outputs.token }}
fetch-depth: 0

- uses: getsentry/craft@v2
with:
version: ${{ inputs.version }}
force: ${{ inputs.force }}
publish_repo: self
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
42 changes: 42 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Agents

## Project Overview

Fossilize is a CLI tool that creates Node.js Single Executable Applications (SEA) for multiple platforms. It bundles a Node.js app using esbuild, downloads platform-specific Node.js binaries, and injects the bundle using postject.

## Tech Stack

- **Language:** TypeScript (type-check only via `tsc --noEmit`, bundled by tsup)
- **Build:** tsup (ESM, code-splitting, minification)
- **Package manager:** npm (not pnpm/yarn)
- **Node version:** Pinned via Volta in package.json (`22.14.0`)
- **CLI framework:** Stricli

## Release & Publishing

This repo uses [getsentry/craft](https://github.com/getsentry/craft) for automated releases, following the `publish_repo: self` pattern (publish issues are created in this repo, not a separate publish repo).

### Release flow
1. Maintainer triggers the **Release** workflow (`workflow_dispatch`) with version `auto` or explicit
2. Craft creates `release/X.Y.Z` branch, bumps `package.json`, generates `CHANGELOG.md`, opens publish issue
3. CI runs on the release branch — `build` + `test` + `artifacts` jobs (artifacts packs npm tarball)
4. Maintainer adds `accepted` label to the publish issue
5. **Publish** workflow fires, runs `craft publish` which publishes to npm (OIDC) and creates a GitHub Release
6. Issue auto-closes on success

### Key files
- `.craft.yml` — Craft configuration (npm + github targets)
- `.github/workflows/build.yml` — CI: build, smoke test, artifact packing on release branches
- `.github/workflows/release.yml` — Manual trigger for `craft prepare`
- `.github/workflows/publish.yml` — Issue-label-triggered `craft publish`

### Prerequisites for releasing
- GitHub App with `contents: write` and `issues: write` permissions
- Repo variable `APP_ID` and secret `APP_PRIVATE_KEY`
- GitHub environment `production` on the repo
- npm OIDC provenance linked for the `fossilize` package

### npm publishing
- Uses OIDC authentication (no `NPM_TOKEN` secret needed)
- Package is published with `public` access
- The `artifacts` job in CI packs the tarball using `npm pack` after downloading the pre-built `dist/` artifact
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"repository": "github:BYK/fossilize",
"license": "MIT",
"type": "module",
"version": "0.6.0",
"version": "0.5.0",
"keywords": [
"node",
"sea",
Expand Down
Loading