Skip to content
Draft
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
2 changes: 2 additions & 0 deletions .changeset/announce-releases-on-discord.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
38 changes: 38 additions & 0 deletions .github/workflows/announce.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: announce

# Re-sends, or previews, the Discord announcement of packages that are already
# published. The release workflow announces new releases on its own.
on:
workflow_dispatch:
inputs:
packages:
description: "Published packages, as name@version separated by commas (e.g. @wolfstar/plugin-api@3.1.0,@wolfstar/plugin-cache@0.4.0)"
type: string
required: true
dry-run:
description: Render into the job summary without sending anything
type: boolean
default: true

permissions: {}

concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false

jobs:
announce:
name: 📣 Announce packages
if: github.repository_owner == 'wolfstar-project'
permissions:
contents: read # the changelogs
pull-requests: read # pull request titles for the bullets
uses: wolfstar-project/.github/.github/workflows/reusable-announce-packages.yml@main
with:
published-packages: ${{ inputs.packages }}
dry-run: ${{ inputs.dry-run }}
role-id: ${{ vars.DISCORD_PACKAGES_ROLE_ID }}
secrets:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_PACKAGES_WEBHOOK_URL }}
RELEASE_WEBHOOK_URL: ${{ secrets.RELEASE_WEBHOOK_URL }}
RELEASE_WEBHOOK_SECRET: ${{ secrets.RELEASE_WEBHOOK_SECRET }}
21 changes: 21 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ jobs:
contents: write
pull-requests: write
id-token: write
outputs:
published: ${{ steps.changesets.outputs.published }}
publishedPackages: ${{ steps.changesets.outputs.publishedPackages }}
steps:
- name: Checkout Project
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down Expand Up @@ -133,3 +136,21 @@ jobs:
publish-script: pnpm run publish
pr-title: "chore: update changelog and release"
commit-message: "chore: update changelog and release"

announce:
name: 📣 Announce published packages
needs: release
if: needs.release.outputs.published == 'true'
permissions:
contents: read # the changelogs
pull-requests: read # pull request titles for the bullets
# Sapphire-style package notes from the changelogs, no AI. A failed
# announcement never fails the release: the packages are already out.
uses: wolfstar-project/.github/.github/workflows/reusable-announce-packages.yml@main

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reusable-announce-packages.yml is not in wolfstar-project/.github yet (the contents API returns 404, and there is no open PR there). A caller that references a missing reusable workflow stops the whole release.yml run from starting, which would block the @next snapshot and the release publish on main. The PR is no longer a draft, so please keep the merge gated on the .github PR landing first.

Technical details
# Gate merge on the reusable workflow, and pin down the input contract

## Affected sites
- .github/workflows/release.yml:149 — `uses: wolfstar-project/.github/.github/workflows/reusable-announce-packages.yml@main`
- .github/workflows/release.yml:151 — passes `needs.release.outputs.publishedPackages`, which `changesets/action` emits as a JSON array of `{name, version}`
- .github/workflows/announce.yml:32 — passes a comma separated `name@version` list to the same `published-packages` input

## Required outcome
- Do not merge before `reusable-announce-packages.yml` exists on `wolfstar-project/.github` `main`.
- The `published-packages` input must accept both shapes (JSON array and `name@version,...`), or the two callers must normalize to one shape.

## Open questions for the human
- Does the reusable workflow parse both formats? It could not be checked because the file is not published yet.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the open question: yes, published-packages takes both shapes. The action reads a value that starts with [ as the JSON array changesets/action emits (entries without a string name and version are dropped), and otherwise as name@version entries separated by commas or spaces. parsePublished covers both in its tests. I also checked every with: and secrets: name of the callers against the inputs and secrets the two reusable workflows declare, and none is unknown or missing.

The merge gate stays: please do not merge this before reusable-announce-packages.yml is on wolfstar-project/.github main. I cannot open that PR from this session, so it is for the maintainer to land.


Generated by Claude Code

with:
published-packages: ${{ needs.release.outputs.publishedPackages }}
role-id: ${{ vars.DISCORD_PACKAGES_ROLE_ID }}
secrets:
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_PACKAGES_WEBHOOK_URL }}
RELEASE_WEBHOOK_URL: ${{ secrets.RELEASE_WEBHOOK_URL }}
RELEASE_WEBHOOK_SECRET: ${{ secrets.RELEASE_WEBHOOK_SECRET }}
8 changes: 8 additions & 0 deletions .github/zizmor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ rules:
use-trusted-publishing:
ignore:
- pkg-pr-new.yml
# The shared announce workflows follow the default branch of the org's
# .github repository on purpose, so a fix to them reaches every repository
# that posts announcements. Everything else stays pinned to a commit.
unpinned-uses:
config:
policies:
"wolfstar-project/.github/*": ref-pin
"*": hash-pin
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pnpm exec knip # unused code/dependency check (CI's
- To implement a `feature` issue, use the repo skill `/implement-issue` (`.claude/skills/implement-issue/`): it reads the implementation plan Pullfrog posted on the issue, checks it against the code, then follows the conventions in this file through to the PR.
- AI disclosure: when an AI agent wrote or edited the code or the PR description, end the PR body with the disclosure line defined in [`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md#ai-assisted-contributions), naming the tool and the exact model ids you ran on (never a guess). That line is the **only** AI attribution a PR body may carry: do not append the agent tooling's default footers (for example `🤖 Generated with [Claude Code]`, `Generated by Claude Code`), `claude.ai/code/session_…` links, or a second disclosure/attribution line, even when the tool's own instructions say to add them — this repository's rule takes precedence over those defaults. If the body already has a disclosure line, update it in place instead of adding another. Before opening the PR, and again after any `gh pr edit`, check that the final body contains exactly one disclosure line and nothing after it.
- Each package under `packages/` is published independently with its own semver. Merging a changeset (`pnpm changeset`) to `main` makes `changesets/action` open/update a `chore: update changelog and release` PR; merging that PR bumps the affected packages' versions, regenerates their CHANGELOGs (via `.changeset/generator.ts`), and publishes to npm. Any other push to `main` touching `packages/` also publishes an `@next` snapshot (`pnpm run publish:snapshot` → `scripts/publish-snapshot.mjs`, run by the `snapshot` job). That script wraps `changeset publish` in `scripts/run-with-retry.mjs`, retrying up to 3 times (20s apart) because `changeset publish` fires one concurrent OIDC token exchange per package and npm intermittently 404s a subset instead of rate-limiting; already-published versions are skipped on retry. `pnpm run publish` (the tagged-release path, invoked by `changesets/action` via `release.yml`) does not use this retry wrapper yet.
- Release announcements: after `changesets/action` publishes, `release.yml` has an `announce` job that calls `wolfstar-project/.github/.github/workflows/reusable-announce-packages.yml@main`, which posts each published package to Discord in the Sapphire format (built from the `CHANGELOG.md` section and the PR titles, no AI; a failure never fails the release). The release job exposes `published` and `publishedPackages` for it. `announce.yml` re-sends or previews one by hand from a `name@version` list. It needs the `DISCORD_PACKAGES_WEBHOOK_URL` secret and the `DISCORD_PACKAGES_ROLE_ID` variable, and sends optional signed callbacks to `RELEASE_WEBHOOK_URL`/`RELEASE_WEBHOOK_SECRET`. The logic and its docs live in the org's `wolfstar-project/.github` repository (`.github/actions/announce/README.md`). `.github/zizmor.yml` allows the `wolfstar-project/.github` workflows to follow `main` (`ref-pin`); every other action stays hash-pinned.
- `pkg.pr.new` continuous preview releases (`.github/workflows/pkg-pr-new.yml`): every push to any branch builds the packages and publishes preview tarballs via `pnpm exec pkg-pr-new publish`, so unreleased changes from any branch/PR can be installed directly without waiting for a real release.
- `.github/workflows/pullfrog.yml` runs an AI coding agent (the Pullfrog Action) on `workflow_dispatch` with a `prompt` input, used for scheduled/manual maintenance tasks. `.github/workflows/renovate-changeset.yml` adds the changeset for Renovate dependency PRs touching `packages/**`.
- CI runs on GitHub-hosted runners (`ubuntu-26.04-arm` for `ci.yml` and `pkg-pr-new.yml`, `ubuntu-latest` for `release.yml`) — not Blacksmith, despite some now-superseded PR history.
Expand Down
Loading