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
6 changes: 5 additions & 1 deletion .changeset/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Changesets

This folder is managed by `@changesets/cli`. Use it to record release notes,
version `@anarchitecture/madrigal`, and publish the package to npm.
version `@anarchitecture/madrigal`, and prepare an explicit release.

Common workflow:

Expand All @@ -10,3 +10,7 @@ pnpm changeset
pnpm version-packages
pnpm release
```

Merges to `main` create version PRs only. Publish the release tarball by pushing
an `anarchitecture-madrigal@<version>` tag or by running the GitHub Actions
tarball workflow manually with the version from `package.json`.
102 changes: 102 additions & 0 deletions .github/workflows/release-tarball.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Publish tarball to GitHub Release

# Explicit distribution channel while main-branch publishing is disabled. Packs
# @anarchitecture/madrigal and attaches the .tgz to a GitHub Release, so
# consumers can install it directly:
#
# npm install https://github.com/block/madrigal/releases/download/<tag>/<file>.tgz
#
# Triggered by pushing a tag of the form `anarchitecture-madrigal@<version>` or
# by manual workflow_dispatch.

on:
push:
tags:
- "anarchitecture-madrigal@*"
workflow_dispatch:
inputs:
version:
description: "Version to release (must match package.json)"
required: true

permissions:
contents: write

concurrency:
group: tarball-release-${{ github.ref }}
cancel-in-progress: false

jobs:
tarball:
name: Pack and release
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

# No setup-node and no pnpm/action-setup -- both would trip zizmor's
# cache-poisoning rule because any GitHub-official setup action is
# treated as cache-capable regardless of whether caching is enabled.
# ubuntu-latest ships Node 20 + corepack, which satisfies our
# engines.node (>=18). Corepack reads `packageManager` from root
# package.json to install the exact pinned pnpm version with no
# cross-branch cache store.
- run: node --version && corepack enable

- run: pnpm install --frozen-lockfile --registry=https://registry.npmjs.org

- run: npm ci --prefix src/dev/ui --no-audit --no-fund --registry=https://registry.npmjs.org --replace-registry-host=always

- name: Build
run: pnpm build

- name: Validate tag
env:
EVENT_NAME: ${{ github.event_name }}
INPUT_VERSION: ${{ inputs.version }}
REF_NAME: ${{ github.ref_name }}
run: |
PACKAGE_VERSION="$(node -e "console.log(JSON.parse(require('fs').readFileSync('package.json', 'utf8')).version)")"
if [ "$EVENT_NAME" = "push" ]; then
EXPECTED_TAG="anarchitecture-madrigal@$PACKAGE_VERSION"
if [ "$REF_NAME" != "$EXPECTED_TAG" ]; then
echo "Tag must be $EXPECTED_TAG for package.json version $PACKAGE_VERSION" >&2
exit 1
fi
elif [ "$INPUT_VERSION" != "$PACKAGE_VERSION" ]; then
echo "Input version must match package.json version $PACKAGE_VERSION" >&2
exit 1
fi

- name: Pack
run: |
mkdir -p dist-tarball
pnpm pack --pack-destination "$GITHUB_WORKSPACE/dist-tarball"
ls -la dist-tarball

# Resolve the release tag. Inputs from workflow_dispatch are attacker-
# controlled (anyone with Actions write can trigger). Pass them in via
# `env:` and reference as shell variables so they can't be interpolated
# as shell syntax -- that's what the semgrep shell-injection rule wants.
- name: Resolve tag
id: tag
env:
EVENT_NAME: ${{ github.event_name }}
INPUT_VERSION: ${{ inputs.version }}
run: |
if [ "$EVENT_NAME" = "push" ]; then
TAG="$GITHUB_REF_NAME"
else
TAG="anarchitecture-madrigal@$INPUT_VERSION"
fi
echo "tag=$TAG" >> "$GITHUB_OUTPUT"

- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.tag.outputs.tag }}
run: |
gh release create "$TAG" \
--title "$TAG" \
--generate-notes \
dist-tarball/*.tgz
17 changes: 4 additions & 13 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Release
name: Version Packages

on:
push:
Expand All @@ -12,11 +12,10 @@ concurrency:
permissions:
contents: write
pull-requests: write
id-token: write

jobs:
release:
name: Version or publish
version:
name: Create Release PR
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
Expand All @@ -30,22 +29,14 @@ jobs:
with:
node-version: '22'
cache: pnpm
registry-url: https://registry.npmjs.org

- run: pnpm install --frozen-lockfile --registry=https://registry.npmjs.org

- run: npm ci --prefix src/dev/ui --no-audit --no-fund --registry=https://registry.npmjs.org --replace-registry-host=always

- run: pnpm build

- name: Create Release PR or publish
- name: Create Release PR
uses: changesets/action@6a0a831ff30acef54f2c6aa1cbbc1096b066edaf # v1.7.0
with:
publish: npm publish --access public --provenance
version: pnpm changeset version
commit: "chore: version packages"
title: "chore: version packages"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.MADRIGAL_NPM_PUBLISH_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.MADRIGAL_NPM_PUBLISH_TOKEN }}
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,18 +317,29 @@ ln -sf "$(pwd)/skills/{skill-name}/SKILL.md" ~/.claude/skills/{skill-name}/SKILL
## Release Workflow

Madrigal uses [Changesets](https://github.com/changesets/changesets) for
versioning and npm publishing.
versioning.

For a release-bearing change, run:

```bash
pnpm changeset
```

After the change lands on `main`, the `Release` GitHub Actions workflow creates
a version PR when changesets are pending. When that version PR lands, the same
workflow builds Madrigal and publishes it to npm with provenance. The workflow
expects the npm automation token in `MADRIGAL_NPM_PUBLISH_TOKEN`.
After the change lands on `main`, the `Version Packages` GitHub Actions
workflow creates a version PR when changesets are pending. Merging to `main`
does not publish Madrigal.

To publish a GitHub Release tarball, merge the version PR and push a matching
tag:

```bash
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('package.json', 'utf8')).version)")
git tag "anarchitecture-madrigal@$VERSION"
git push origin "anarchitecture-madrigal@$VERSION"
```

The `Publish tarball to GitHub Release` workflow can also be run manually with
the package version from `package.json`.

Manual release commands are also available:

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"clean": "rm -rf dist",
"changeset": "changeset",
"version-packages": "changeset version",
"release": "pnpm build && changeset publish",
"release": "pnpm build && pnpm pack",
"prepublishOnly": "pnpm build",
"prepare": "lefthook install"
},
Expand Down
Loading