Skip to content

release

release #33

Workflow file for this run

name: release
run-name: release
on:
push:
# NOTE: pushes from CI without a PAT will not trigger the tags below
tags:
- "jco-v[0-9]+.[0-9]+.[0-9]+*"
- "jco-v[0-9]+.[0-9]+.[0-9]+-*"
- "preview2-shim-v[0-9]+.[0-9]+.[0-9]+*"
- "preview2-shim-v[0-9]+.[0-9]+.[0-9]+-*"
- "js-component-bindgen-v[0-9]+.[0-9]+.[0-9]+*"
- "js-component-bindgen-v[0-9]+.[0-9]+.[0-9]+-*"
branches:
- "prep-release-jco-v[0-9]+.[0-9]+.[0-9]+*"
- "prep-release-jco-v[0-9]+.[0-9]+.[0-9]+-*"
- "prep-release-preview2-shim-v[0-9]+.[0-9]+.[0-9]+*"
- "prep-release-preview2-shim-v[0-9]+.[0-9]+.[0-9]+-*"
- "prep-release-js-component-bindgen-v[0-9]+.[0-9]+.[0-9]+*"
- "prep-release-js-component-bindgen-v[0-9]+.[0-9]+.[0-9]+-*"
workflow_dispatch:
inputs:
project:
type: choice
required: true
default: "jco"
options:
- jco
- js-component-bindgen
- preview2-shim
description: |
Project to tag for release (ex. `0.1.0`)
version:
type: string
required: true
description: |
Version tag to release (e.x. `0.1.0`, `0.2.0`)
permissions:
contents: none
jobs:
meta:
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.meta.outputs.version }}
project: ${{ steps.meta.outputs.project }}
project-dir: ${{ steps.project-meta.outputs.project-dir }}
is-js-project: ${{ steps.project-meta.outputs.is-js-project }}
is-rust-project: ${{ steps.project-meta.outputs.is-rust-project }}
artifacts-glob: ${{ steps.project-meta.outputs.artifacts-glob }}
artifact-name: ${{ steps.project-meta.outputs.artifact-name }}
next-release-tag: ${{ steps.project-meta.outputs.next-release-tag }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: taiki-e/cache-cargo-install-action@4d586f211d9b0bca9e7b59e57e2a0febf36c0929 # v2.1.1
with:
tool: cargo-get
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ">=22"
- name: Cache npm install
id: cache-node-modules
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
key: node-modules-dev-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json') }}
path: |
node_modules
- name: Install debug NPM packages
run: |
npm install -D
- name: Collect metadata
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
id: meta
with:
script: |
if (context.payload.inputs?.project && context.payload.inputs?.version) {
core.setOutput('project', context.payload.inputs.project);
core.setOutput('version', context.payload.inputs.version);
return;
}
if (context.ref.startsWith('refs/tags/')) {
match = context.ref.replace('refs/tags/', '').match(/^(.*)-v([^\s]+)$/);
} else if (context.ref.startsWith('refs/heads/')) {
match = context.ref.replace('refs/heads/', '').match(/^prep-release-(.+)-v([^\s]+)$/);
} else {
throw new Error(`Unexpected context ref [${context.ref}]`);
}
if (!match) { throw new Error(`Failed to parse tag/branch: [${context.ref}]`); }
const [_, project, version] = match;
core.setOutput('project', project);
core.setOutput('version', version);
- name: Gather project metadata
id: project-meta
env:
NEXT_VERSION: ${{ steps.meta.outputs.version }}
PROJECT: ${{ steps.meta.outputs.project }}
shell: bash
run: |
if [[ $NEXT_VERSION == v* ]]; then
echo "::error::next version [$NEXT_VERSION] starts with 'v' -- enter only the semver version (ex. '0.1.0', not 'v0.1.0')";
exit 1;
fi
case $PROJECT in
jco)
export PROJECT_DIR=$PWD;
export CURRENT_VERSION=$(node -e "process.stdout.write(require(process.env.PROJECT_DIR + '/package.json').version)");
export IS_JS_PROJECT=true;
export ARTIFACTS_GLOB="bytecodealliance-jco-*.tgz";
export ARTIFACT_NAME="bytecodealliance-jco-$NEXT_VERSION.tgz";
;;
preview2-shim)
export PROJECT_DIR="$PWD/packages/${{ steps.meta.outputs.project }}";
export CURRENT_VERSION=$(node -e "process.stdout.write(require(process.env.PROJECT_DIR + '/package.json').version)");
export IS_JS_PROJECT=true;
export ARTIFACTS_GLOB="packages/preview2-shim/bytecodealliance-preview2-shim-*.tgz";
export ARTIFACT_NAME="bytecodealliance-preview2-shim-$NEXT_VERSION.tgz";
;;
js-component-bindgen)
export PROJECT_DIR="$PWD/crates/${{ steps.meta.outputs.project }}";
export CURRENT_VERSION=$(cargo get package.version --terminator Nul --entry=$PROJECT_DIR);
export IS_RUST_PROJECT=true;
export ARTIFACTS_GLOB="target/package/js-component-bindgen-*.crate";
export ARTIFACT_NAME="js-component-bindgen-$NEXT_VERSION.crate";
;;
*)
echo "unexpected project type (neither Rust nor JS)";
exit 1;
esac
export IS_PRERELEASE=$(node scripts/semver-is-prerelease.mjs $NEXT_VERSION);
echo -e "is-prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT;
export PRERELEASE_TAG=$(node scripts/semver-get-prerelease.mjs $NEXT_VERSION);
echo -e "prerelease-tag=$PRERELEASE_TAG" >> $GITHUB_OUTPUT;
echo -e "project-dir=$PROJECT_DIR" >> $GITHUB_OUTPUT;
echo -e "is-rust-project=$IS_RUST_PROJECT" >> $GITHUB_OUTPUT;
echo -e "is-js-project=$IS_JS_PROJECT" >> $GITHUB_OUTPUT;
echo -e "artifacts-glob=$ARTIFACTS_GLOB" >> $GITHUB_OUTPUT;
echo -e "artifact-name=$ARTIFACT_NAME" >> $GITHUB_OUTPUT;
echo -e "next-release-tag=${PROJECT}-v${NEXT_VERSION}" >> $GITHUB_OUTPUT;
pack-crate-release:
if: ${{ needs.meta.outputs.is-rust-project == 'true' }}
runs-on: ubuntu-24.04
needs:
- meta
permissions:
actions: write
id-token: write
attestations: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
with:
shared-key: jco-${{ hashFiles('Cargo.lock') }}
- name: Release crate (dry run)
working-directory: ${{ needs.meta.outputs.project-dir }}
run: |
cargo publish --locked --dry-run
- name: Create release package
working-directory: ${{ needs.meta.outputs.project-dir }}
run: |
cargo package
- uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0
with:
subject-path: ${{ needs.meta.outputs.artifacts-glob }}
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
if-no-files-found: error
name: ${{ needs.meta.outputs.project }}
path: |
${{ needs.meta.outputs.artifacts-glob }}
pack-npm-release:
if: ${{ needs.meta.outputs.is-js-project == 'true' }}
runs-on: ubuntu-24.04
needs:
- meta
permissions:
id-token: write
attestations: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8
with:
shared-key: jco-${{ hashFiles('Cargo.lock') }}
# NOTE: we must use a node version new-enough to have --experimental-wasm-jspi
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ">=22"
- name: Cache npm install
id: cache-node-modules
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
key: node-modules-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('package.json') }}
path: |
node_modules
- name: Install NPM packages
run: |
npm install
- name: Create release package
working-directory: ${{ needs.meta.outputs.project-dir }}
run: |
npm pack
- uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0
with:
subject-path: ${{ needs.meta.outputs.artifacts-glob }}
- uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
if-no-files-found: error
name: ${{ needs.meta.outputs.project }}
path: |
${{ needs.meta.outputs.artifacts-glob }}
test-crate-release:
runs-on: ubuntu-24.04
needs:
- meta
- pack-crate-release
steps:
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
path: artifacts
- name: Test built crates.io crate
if: ${{ needs.meta.outputs.project == 'js-component-bindgen' }}
shell: bash
run: |
mkdir -p /tmp/${{ needs.meta.outputs.project }}
cp -r artifacts/${{ needs.meta.outputs.project }}/* /tmp/${{ needs.meta.outputs.project }}/
cd /tmp/${{ needs.meta.outputs.project }}
tar --strip-components=1 -xvf ${{ needs.meta.outputs.artifact-name }}
rm Cargo.toml.orig
cargo build
test-npm-release:
runs-on: ubuntu-24.04
needs:
- meta
- pack-npm-release
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
path: artifacts
- name: Test built jco NPM package
if: ${{ needs.meta.outputs.project == 'jco' }}
shell: bash
run: |
export PACKAGE_DIR=${{ github.workspace }}/artifacts/${{ needs.meta.outputs.project }}/${{ needs.meta.outputs.artifact-name }}
cp -r examples/components/http-hello-world /tmp/test
cd /tmp/test
npm install --save $PACKAGE_DIR
npm run all
crate-publish:
runs-on: ubuntu-24.04
needs:
- meta
- test-crate-release
steps:
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
path: artifacts
- name: Publish ${{ needs.meta.outputs.project }} to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_API_KEY }}
run: |
export OPT_DRY_RUN="--dry-run"
if [ "tag" == "${{ github.ref_type }}" ]; then
export OPT_DRY_RUN="";
fi
mkdir -p /tmp/${{ needs.meta.outputs.project }}
cp -r artifacts/${{ needs.meta.outputs.project }}/* /tmp/${{ needs.meta.outputs.project }}/
cd /tmp/${{ needs.meta.outputs.project }}
tar --strip-components=1 -xvf ${{ needs.meta.outputs.artifact-name }}
rm Cargo.toml.orig
cargo publish $OPT_DRY_RUN
npm-publish:
runs-on: ubuntu-24.04
needs:
- meta
- test-npm-release
steps:
# NOTE: we need to checkout to pull npmrc
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: |
.npmrc
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
path: artifacts
- name: Publish ${{ needs.meta.outputs.project }} to NPM
env:
NPM_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
shell: bash
run: |
export PACKAGE_DIR=${{ github.workspace }}/artifacts/${{ needs.meta.outputs.project }}/${{ needs.meta.outputs.artifact-name }}
export OPT_DRY_RUN="--dry-run"
if [ "tag" == "${{ github.ref_type }}" ]; then
export OPT_DRY_RUN="";
fi
export OPT_RELEASE_TAG=""
if [ "true" == "${{ needs.project-meta.outputs.is-prerelease }}" ]; then
export OPT_RELEASE_TAG="--tag ${{ needs.project-meta.outputs.prerelease-tag }}";
fi
npm publish $OPT_DRY_RUN $OPT_RELEASE_TAG $PACKAGE_DIR
create-gh-release:
runs-on: ubuntu-24.04
if: always()
needs:
- meta
- test-crate-release
- test-npm-release
- npm-publish
- crate-publish
permissions:
contents: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
- uses: taiki-e/install-action@d125c0a83576d3c0c86ac610c708b38d3565af4e # v2.47.15
with:
fallback: none
tool: git-cliff
# Re-generate the current changelog so we can use it in the GH release announcement
- name: Re-generate current changelog
working-directory: ${{ needs.meta.outputs.project-dir }}
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_PAT || secrets.GITHUB_TOKEN }}
GITHUB_REPO: ${{ github.repository }}
run: |
git cliff \
--repository=${{ github.workspace }}/.git \
--latest \
--tag ${{ needs.meta.outputs.next-release-tag }} > CHANGELOG.current
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
path: artifacts
- name: Create GH release
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2
with:
token: ${{ secrets.RELEASE_PAT || github.token }}
prerelease: ${{ github.ref_type != 'tag' }}
draft: ${{ github.ref_type != 'tag' }}
tag_name: ${{ needs.meta.outputs.next-release-tag }}
generate_release_notes: false
body_path: ${{ needs.meta.outputs.project-dir }}/CHANGELOG.current
files: |
./artifacts/*/*