Skip to content

chore(sdk): track dxos/main@0132aab (#34) #37

chore(sdk): track dxos/main@0132aab (#34)

chore(sdk): track dxos/main@0132aab (#34) #37

Workflow file for this run

name: Release
# Changesets-driven release, trunk-based on `main` — there is no long-lived release branch, matching
# dxos/dxos. Every push to `main`:
# - with changesets pending, opens/updates a "Version Packages" PR (bumps each changed plugin's
# version + CHANGELOG). Merging that PR is the human gate;
# - with none left, publishes the bumped plugins to npm (which also tags each version) and then to
# the AT Protocol registry via `dx registry publish`.
#
# Dispatching with `registry_only` skips npm and republishes the current versions to the registry, so
# a registry failure can be retried without a version bump — npm is append-only, so a plain re-run
# would find its half already done and never reach the registry.
#
# Plugins carry independent version lines (`fixed: []`), but share one Version Packages PR, so a
# release ships whatever accumulated since the last one — independent numbers, coupled timing.
#
# npm auth is a trusted publisher (OIDC), not a token: this filename is load-bearing, because each
# plugin's trusted publisher on npmjs.com names `release.yml`, and publishing from a workflow with any
# other filename fails OIDC. A plugin npm has never seen has no trusted publisher yet, so it stays
# `private: true` until someone publishes it once by hand and configures one — enforced in CI by
# `scripts/check-packages-published.mjs`.
on:
push:
branches: [main]
workflow_dispatch:
inputs:
registry_only:
description: 'Republish current versions to the registry only, skipping npm. Retries a failed registry publish.'
type: boolean
default: false
cli_package:
description: 'npm spec for the dx CLI, overriding the pinned default — e.g. a pkg.pr.new URL for a branch build.'
required: false
permissions:
contents: write
pull-requests: write
id-token: write # npm trusted-publisher OIDC + provenance.
jobs:
release:
runs-on: ubuntu-latest
env:
# Exposed so a step condition can branch on token presence: secrets are not allowed in `if:`.
GH_DXOS_BOT_PAT: ${{ secrets.GH_DXOS_BOT_PAT }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# changesets/action pushes over a `~/.netrc` it writes from `github-token`, and a persisted
# checkout credential outranks netrc (`http.extraheader` is an explicit Authorization
# header), which would silently put the Version PR's commits back on GITHUB_TOKEN.
persist-credentials: false
- name: Release guard — never publish against an unreleased SDK
# Matches quoted @dxos/* entry values only, so the guard neither trips on the explanatory
# pkg.pr.new mentions in the file header nor on a prerelease pin in the external catalog,
# and does not go blind once the catalog outgrows a fixed line window.
run: |
if grep -qE "^[[:space:]]+'@dxos/[^']+':[[:space:]]*'[^']*pkg\.pr\.new" pnpm-workspace.yaml; then
echo "::error::Refusing to release: the dxos catalog points at a pkg.pr.new pin. Run the SDK npm release workflow first (see RELEASING.md)."
exit 1
fi
if grep -qE "^[[:space:]]+'@dxos/[^']+':[[:space:]]*'[^']*[0-9]+\.[0-9]+\.[0-9]+-" pnpm-workspace.yaml; then
echo "::error::Refusing to release: the dxos catalog points at a prerelease version. Run the SDK npm release workflow first (see RELEASING.md)."
exit 1
fi
- uses: ./.github/actions/setup
# `files` ships dist/, so the library has to exist before changesets packs the tarball. The
# registry bundle is not built here — `dx registry publish` runs the `buildCommand` declared
# in each plugin's dx.config.ts itself.
- run: moon run :build
- name: Warn when the bot PAT is missing
if: ${{ env.GH_DXOS_BOT_PAT == '' }}
run: |
echo "::warning::GH_DXOS_BOT_PAT is not set; the Version Packages PR is owned by" \
"github-actions[bot], so its checks are parked in action_required until approved by hand." \
"See RELEASING.md."
# `changeset publish` pushes to npm and tags each released version; `publishedPackages` then
# reports exactly what this run released, which drives the registry publish below.
- id: changesets
if: ${{ !inputs.registry_only }}
uses: changesets/action@v1
with:
# dxos-bot's PAT, not GITHUB_TOKEN: GitHub's recursion guard parks every `pull_request` run
# a GITHUB_TOKEN update triggers in `action_required`, so a GITHUB_TOKEN-owned Version PR
# reports zero check runs until a human approves each one by hand. The action reads
# `process.env.GITHUB_TOKEN` ahead of this input, so that env var must stay unset here.
github-token: ${{ secrets.GH_DXOS_BOT_PAT || secrets.GITHUB_TOKEN }}
version: pnpm version-packages
publish: pnpm exec changeset publish
env:
NPM_CONFIG_PROVENANCE: 'true' # provenance via OIDC; trusted publisher means no NPM_TOKEN.
# npm is the library channel; the registry is what Composer installs from. Both ship the same
# version, from different build outputs — dist/ for npm, out/ for the registry.
# Runs on a `registry_only` dispatch even though nothing was published in that run: npm is
# append-only, so once a version is up the release cannot be replayed to reach the registry
# half, and this is the half that talks to two external services.
- name: Publish released plugins to the registry
if: ${{ inputs.registry_only || steps.changesets.outputs.published == 'true' }}
env:
ALL: ${{ inputs.registry_only }}
# Pinned to a pkg.pr.new preview: npm's @dxos/cli@0.10.0 cannot read a dx.config.ts from a
# plugin directory (fixed in dxos/dxos#12514) and lacks DX_HUB_API_KEY upload auth
# (dxos/dxos#12528). Override with the DX_CLI_PACKAGE repo variable, and drop the default
# once a working CLI is on npm. Installing the single linux-x64 package rather than the
# launcher avoids fetching all five platforms.
DX_CLI_PACKAGE: ${{ inputs.cli_package || vars.DX_CLI_PACKAGE || 'https://pkg.pr.new/dxos/dxos/@dxos/cli-linux-x64@d7b0a3b' }}
PUBLISHED: ${{ steps.changesets.outputs.publishedPackages }}
ATPROTO_HANDLE: ${{ secrets.ATPROTO_HANDLE }}
ATPROTO_APP_PASSWORD: ${{ secrets.ATPROTO_APP_PASSWORD }}
# Authenticates the edge upload in place of a hub-identity VP — CI holds no HALO identity.
DX_HUB_API_KEY: ${{ secrets.DX_HUB_API_KEY }}
run: |
# node comes from proto, whose global bin is not on PATH, so a `-g` install lands somewhere
# the shell will not find. npm reports the prefix it is about to install into, so ask it.
export PATH="$(npm prefix -g)/bin:${PATH}"
npm install -g "${DX_CLI_PACKAGE}"
# Fail fast on a broken CLI rather than part-way through publishing.
dx --version
# pnpm resolves the workspace glob and reports `private`, so the publishable set never has
# to be re-derived here. A `registry_only` retry takes all of them, since `publishedPackages`
# is empty in a run that published nothing.
pnpm list --recursive --depth=-1 --json \
| jq -r --argjson all "${ALL:-false}" --argjson published "${PUBLISHED:-[]}" '
($published | map(.name)) as $names
| .[]
| select(.name and (.private | not))
| select($all or (.name as $name | $names | any(. == $name)))
| .path
' > released-dirs.txt
echo "Publishing $(grep -c . released-dirs.txt || true) plugin(s) to the registry."
while read -r dir; do
[ -n "${dir}" ] || continue
echo "::group::Publishing ${dir}"
dx registry publish --dir "${dir}"
echo "::endgroup::"
done < released-dirs.txt