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
22 changes: 5 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Reusable GitHub Actions for Variable Land.

## Actions

- [`preview-release`](actions/preview-release): publishes a per-PR preview release of a standalone library, a single package outside a workspace, to npm, with OIDC first and an optional `NPM_TOKEN` fallback. The PR comment comes from the [`vland-bot`](https://bot.variable.land) server (`mode: server`, the default) or from a separate job that never runs PR code (`mode: publish` and `mode: comment`, with [`preview-comment`](#reusable-workflows)).
- [`monorepo-preview-release`](actions/monorepo-preview-release): publishes a per-PR preview release of the changed packages in a pnpm monorepo to npm, with OIDC first and an optional `NPM_TOKEN` fallback. The PR comment comes from the [`vland-bot`](https://bot.variable.land) server (`mode: server`, the default) or from a separate job that never runs PR code (`mode: publish` and `mode: comment`, with [`preview-comment`](#reusable-workflows)).
- [`preview-release`](actions/preview-release): publishes a per-PR preview release of a standalone library, a single package outside a workspace, to npm, with OIDC first and an optional `NPM_TOKEN` fallback. The PR comment comes from the [`vland-bot`](https://github.com/apps/vland-bot) server (`mode: server`, the default) or from a separate job that never runs PR code (`mode: publish` and `mode: comment`, with [`preview-comment`](#reusable-workflows)).
- [`monorepo-preview-release`](actions/monorepo-preview-release): publishes a per-PR preview release of the changed packages in a pnpm monorepo to npm, with OIDC first and an optional `NPM_TOKEN` fallback. The PR comment comes from the [`vland-bot`](https://github.com/apps/vland-bot) server (`mode: server`, the default) or from a separate job that never runs PR code (`mode: publish` and `mode: comment`, with [`preview-comment`](#reusable-workflows)).
- [`railway-redeploy`](actions/railway-redeploy): redeploys a Railway service through the Railway GraphQL API. It finds the service from `project_id`, `environment` and `service_name`, so it needs no service ID.
- [`setup-pnpm`](actions/setup-pnpm): installs pnpm, upgrades npm, caches the pnpm store and installs the dependencies. **Deprecated:** install node and pnpm with mise instead ([migration](actions/setup-pnpm/README.md#migrating-to-mise)).
- [`setup-bun`](actions/setup-bun): installs Bun at the version in `.bun-version`.
Expand All @@ -15,27 +15,15 @@ Reusable GitHub Actions for Variable Land.

- [`preview-comment`](.github/workflows/preview-comment.yml): job 2 of the two-job preview pattern. It mints a `vland-bot` token for the current repo, with `pull-requests: write`, and upserts the preview release's PR comment from the `packages` output of a `mode: publish` job, without checking out or running PR code. The setup and a caller example are in the [`preview-release`](actions/preview-release/README.md#two-job-previews) and [`monorepo-preview-release`](actions/monorepo-preview-release/README.md#two-job-previews) READMEs.

```yml
preview-comment:
needs: preview
permissions: {}
uses: withvariablelab/gh-actions/.github/workflows/preview-comment.yml@main
with:
action: monorepo-preview-release # or preview-release
packages: ${{ needs.preview.outputs.packages }}
secrets:
VLAND_BOT_PRIVATE_KEY: ${{ secrets.VLAND_BOT_PRIVATE_KEY }}
```

## Versioning

Pin an action to a tag or a commit SHA when you need stability:
Pin an action to a commit SHA when you need stability:

```yml
uses: withvariablelab/gh-actions/actions/<action-name>@<tag-or-sha>
uses: withvariablelab/gh-actions/actions/<action-name>@<sha>
```

`@main` tracks the latest changes on the default branch.
`@main` tracks the latest changes on the default branch. `preview-comment.yml` runs the actions at `@main`, so pinning the workflow to a SHA doesn't pin the comment code.

## Contributing

Expand Down
20 changes: 10 additions & 10 deletions actions/monorepo-preview-release/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ If `preview` fails or is skipped, `needs` skips `preview-comment` too.
| --- | --- | --- | --- |
| `mode` | no | `server` | `server`, `publish` or `comment`. See [Modes](#modes). |
| `github_token` | yes | — | `server` and `publish`: a token for the GitHub API, usually `${{ secrets.GITHUB_TOKEN }}`, to list the PR's changed files. `comment`: a token that can write PR comments, the `vland-bot` token that `preview-comment.yml` mints. |
| `npm_token` | no | — | `server` and `publish` only. An npm classic or automation token. When set, it turns on the OIDC and token fallback mode (see [Authentication modes](#authentication-modes)). |
| `npm_token` | no | — | `server` and `publish` only. An npm classic or automation token. When set, and `GITHUB_WORKSPACE` has no `.npmrc`, it turns on the OIDC and token fallback mode (see [Authentication modes](#authentication-modes)). |
| `publish_mode` | no | detected | `server` and `publish` only. Overrides the [authentication mode](#authentication-modes): `token-only`, `oidc-only` or `oidc-with-token-fallback`. |
| `vland_bot_url` | no | `https://bot.variable.land` | `server` only. The base URL of the `vland-bot` server that gets the notification after the publish. |
| `packages` | in `comment` | — | `comment` only. The `packages` output of a `publish` run, as JSON. |
Expand All @@ -127,12 +127,12 @@ Set in `mode: publish` only:
- `pr-number`: the number of the pull request.
- `head-sha`: the head commit SHA of the pull request.

Each `packages` entry is the same payload that `mode: server` POSTs to `vland-bot` at `POST <vland_bot_url>/v1/github/preview-release`:
Each `packages` entry is one item of the `packages` array that `mode: server` POSTs to `vland-bot` at `POST <vland_bot_url>/v1/github/preview-release`, beside `owner`, `repo`, `prNumber` and `latestCommitSha`:

| Field | Type | Description |
| --- | --- | --- |
| `packageName` | `string` | The npm package name. |
| `nextVersion` | `string` | The published preview version (`<current>-git-<short-sha>`). |
| `nextVersion` | `string` | The published preview version: the prerelease of the current version with the preid `git-<short-sha>`, so `1.2.3` becomes `1.2.4-git-abc1234.0`. |
| `firstTime` | `boolean` | `true` when this run published the package's first version ever. npm makes that version `latest`, and nothing can prevent it (see [First-time publishes & `latest`](#first-time-publishes--latest)), so the comment warns that `pnpm add <pkg>` resolves to a preview build until a stable release moves `latest`. |

## Requirements
Expand All @@ -158,8 +158,8 @@ permissions:

## What a run publishes

- The packages the PR changes, and their workspace dependents, are found through the GitHub API's list of the PR's files.
- Each package gets its version bumped to the prerelease `<current>-git-<short-sha>`.
- The packages the PR changes are found through the GitHub API's list of the PR's files. Any workspace dependency of theirs, direct or transitive, that has never been published to npm is published with them. Packages that depend on a changed package are not added.
- Each package gets its version bumped to its prerelease with the preid `git-<short-sha>`: `1.2.3` becomes `1.2.4-git-abc1234.0`.
- Each package is published to npm under the dist-tag `pr-<pr-number>`.
- Private packages (`"private": true`) are left out.
- A package's **first publish ever** is a special case. npm gives it the `latest` dist-tag and won't let that tag be removed, so the preview becomes the default `pnpm add <pkg>` target until a stable release moves `latest`. The action flags these first publishes, so the PR comment can warn about it. See [First-time publishes & `latest`](#first-time-publishes--latest).
Expand All @@ -168,8 +168,8 @@ permissions:

`server` and `publish` pick one of three npm publishing modes from the workspace's state and the inputs. `publish_mode` overrides the choice.

- **`token-only`**, when `.npmrc` already provides auth: publishes with the existing `.npmrc` credentials, and never adds `--provenance`.
- **`oidc-with-token-fallback`**, when the `npm_token` input is set and `.npmrc` has no auth: publishes each package with OIDC and provenance through `pnpm publish --provenance`. If a package's publish fails **and** that package has never been published to npm, it falls back to `NPM_TOKEN` auth without provenance.
- **`token-only`**, when `GITHUB_WORKSPACE`, the directory the action runs in, has a `.npmrc`, whatever it holds: publishes with the credentials npm finds, and never adds `--provenance`.
- **`oidc-with-token-fallback`**, when the `npm_token` input is set and `GITHUB_WORKSPACE` has no `.npmrc`: publishes each package with OIDC and provenance through `pnpm publish --provenance`. If a package's publish fails **and** that package has never been published to npm, it falls back to `NPM_TOKEN` auth without provenance.
- **`oidc-only`**, in every other case: publishes with OIDC and provenance. Any failure is fatal.

The `oidc-with-token-fallback` mode exists for the **first publishes** of packages that have no Trusted Publisher on npm yet: those land through the token, without provenance, and every other package keeps its provenance attestation.
Expand All @@ -183,7 +183,7 @@ So for a new package, the first PR preview becomes the version that `pnpm add <p
The action doesn't try to fix this at the registry, because it can't. It detects first publishes and reports `firstTime: true`, and the PR comment marks those packages with `†` and a footnote. Each published preview stays installable by tag or by exact version:

- `pnpm add <pkg>@pr-<n>`, by the PR's tag.
- `pnpm add <pkg>@<version>`, by the exact `<current>-git-<short-sha>` version.
- `pnpm add <pkg>@<version>`, by the exact version that the PR comment shows.

The fix is a real release: the normal release pipeline publishes a stable version and moves `latest` to it.

Expand All @@ -192,8 +192,8 @@ The fix is a real release: the normal release pipeline publishes a stable versio
The action runs the real `pnpm` CLI for the work:

- `pnpm list -r --json --depth 0` to list the workspace.
- `pnpm version prerelease --preid git-<sha> --no-git-tag-version` to bump.
- `pnpm publish --tag pr-<n> --no-git-checks [--provenance]` to publish.
- `pnpm version prerelease --preid git-<short-sha> --no-git-tag-version --no-git-checks` to bump.
- `pnpm publish --tag pr-<n> --access public --no-git-checks [--provenance]` to publish.

`pnpm publish` handles `workspace:*` and `catalog:` resolution, `publishConfig` overrides, lifecycle scripts (`prepublishOnly`, `prepack`, `prepare`) and the npm Trusted Publisher OIDC exchange. The action only picks which packages get bumped, and the auth mode.

Expand Down
2 changes: 1 addition & 1 deletion actions/monorepo-preview-release/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@variablelab/monorepo-preview-release",
"version": "0.0.0",
"private": true,
"description": "Action to release packages in a monorepo with a PR related tag",
"description": "Publishes a per-PR preview release of the changed packages in a pnpm workspace to npm, under the dist-tag pr-<n>.",
"license": "MIT",
"author": "rcrd <rcrd@variable.land>",
"type": "module",
Expand Down
20 changes: 10 additions & 10 deletions actions/preview-release/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This action publishes a **per-PR preview release** of a standalone library, a single npm package outside a workspace, and gets a sticky comment with the published version posted on the pull request.

> For a pnpm monorepo, use [`monorepo-preview-release`](../monorepo-preview-release/README.md) instead: it detects the changed packages and their workspace dependents.
> For a pnpm monorepo, use [`monorepo-preview-release`](../monorepo-preview-release/README.md) instead: it detects the changed packages, and publishes with them any workspace dependency that has never been published to npm.

## Modes

Expand Down Expand Up @@ -111,7 +111,7 @@ If `preview` fails or is skipped, `needs` skips `preview-comment` too.
| Input | Required | Default | Description |
| --- | --- | --- | --- |
| `mode` | no | `server` | `server`, `publish` or `comment`. See [Modes](#modes). |
| `npm_token` | no | — | `server` and `publish` only. An npm classic or automation token. When set, it turns on the OIDC and token fallback mode (see [Authentication modes](#authentication-modes)). |
| `npm_token` | no | — | `server` and `publish` only. An npm classic or automation token. When set, and `working_directory` has no `.npmrc`, it turns on the OIDC and token fallback mode (see [Authentication modes](#authentication-modes)). |
| `publish_mode` | no | detected | `server` and `publish` only. Overrides the [authentication mode](#authentication-modes): `token-only`, `oidc-only` or `oidc-with-token-fallback`. |
| `working_directory` | no | `.` | `server` and `publish` only. The directory with the `package.json` to publish, for a library that lives in a subdirectory. |
| `vland_bot_url` | no | `https://bot.variable.land` | `server` only. The base URL of the `vland-bot` server that gets the notification after the publish. |
Expand All @@ -127,12 +127,12 @@ Set in `mode: publish` only:
- `pr-number`: the number of the pull request.
- `head-sha`: the head commit SHA of the pull request.

Each `packages` entry is the same payload that `mode: server` POSTs to `vland-bot` at `POST <vland_bot_url>/v1/github/preview-release`:
Each `packages` entry is one item of the `packages` array that `mode: server` POSTs to `vland-bot` at `POST <vland_bot_url>/v1/github/preview-release`, beside `owner`, `repo`, `prNumber` and `latestCommitSha`:

| Field | Type | Description |
| --- | --- | --- |
| `packageName` | `string` | The npm package name. |
| `nextVersion` | `string` | The published preview version (`<current>-git-<short-sha>`). |
| `nextVersion` | `string` | The published preview version: the prerelease of the current version with the preid `git-<short-sha>`, so `1.2.3` becomes `1.2.4-git-abc1234.0`. |
| `firstTime` | `boolean` | `true` when this run published the package's first version ever. npm makes that version `latest`, and nothing can prevent it (see [First-time publishes & `latest`](#first-time-publishes--latest)), so the comment warns that `pnpm add <pkg>` resolves to a preview build until a stable release moves `latest`. |

## Requirements
Expand All @@ -158,7 +158,7 @@ permissions:

## What a run publishes

- The package in `working_directory`, the repository root by default, gets its version bumped to the prerelease `<current>-git-<short-sha>`.
- The package in `working_directory`, the repository root by default, gets its version bumped to its prerelease with the preid `git-<short-sha>`: `1.2.3` becomes `1.2.4-git-abc1234.0`.
- The package is published to npm under the dist-tag `pr-<pr-number>`.
- A private package (`"private": true`) is skipped.
- A package's **first publish ever** is a special case. npm gives it the `latest` dist-tag and won't let that tag be removed, so the preview becomes the default `pnpm add <pkg>` target until a stable release moves `latest`. The action flags these first publishes, so the PR comment can warn about it. See [First-time publishes & `latest`](#first-time-publishes--latest).
Expand All @@ -167,8 +167,8 @@ permissions:

`server` and `publish` pick one of three npm publishing modes from the directory's state and the inputs. `publish_mode` overrides the choice.

- **`token-only`**, when `.npmrc` already provides auth: publishes with the existing `.npmrc` credentials, and never adds `--provenance`.
- **`oidc-with-token-fallback`**, when the `npm_token` input is set and `.npmrc` has no auth: publishes with OIDC and provenance through `pnpm publish --provenance`. If the publish fails **and** the package has never been published to npm, it falls back to `NPM_TOKEN` auth without provenance.
- **`token-only`**, when `working_directory` has a `.npmrc`, whatever it holds: publishes with the credentials npm finds, and never adds `--provenance`.
- **`oidc-with-token-fallback`**, when the `npm_token` input is set and `working_directory` has no `.npmrc`: publishes with OIDC and provenance through `pnpm publish --provenance`. If the publish fails **and** the package has never been published to npm, it falls back to `NPM_TOKEN` auth without provenance.
- **`oidc-only`**, in every other case: publishes with OIDC and provenance. Any failure is fatal.

The `oidc-with-token-fallback` mode exists for the **first publish** of a package that has no Trusted Publisher on npm yet: it lands through the token, without provenance, and every later publish keeps its provenance attestation.
Expand All @@ -182,16 +182,16 @@ So for a new package, the first PR preview becomes the version that `pnpm add <p
The action doesn't try to fix this at the registry, because it can't. It detects the first publish and reports `firstTime: true`, and the PR comment marks the package with `†` and a footnote. The published preview stays installable by tag or by exact version:

- `pnpm add <pkg>@pr-<n>`, by the PR's tag.
- `pnpm add <pkg>@<version>`, by the exact `<current>-git-<short-sha>` version.
- `pnpm add <pkg>@<version>`, by the exact version that the PR comment shows.

The fix is a real release: the normal release pipeline publishes a stable version and moves `latest` to it.

## How publishing works

The action runs the real `pnpm` CLI for the work:

- `pnpm version prerelease --preid git-<sha> --no-git-tag-version` to bump.
- `pnpm publish --tag pr-<n> --no-git-checks [--provenance]` to publish.
- `pnpm version prerelease --preid git-<short-sha> --no-git-tag-version --no-git-checks` to bump.
- `pnpm publish --tag pr-<n> --access public --no-git-checks [--provenance]` to publish.

`pnpm publish` handles `publishConfig` overrides, lifecycle scripts (`prepublishOnly`, `prepack`, `prepare`) and the npm Trusted Publisher OIDC exchange. The action only handles the bump and picks the auth mode.

Expand Down
2 changes: 1 addition & 1 deletion actions/preview-release/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@variablelab/preview-release",
"version": "0.0.0",
"private": true,
"description": "Action to release a standalone library with a PR related tag",
"description": "Publishes a per-PR preview release of a single package to npm, under the dist-tag pr-<n>.",
"license": "MIT",
"author": "rcrd <rcrd@variable.land>",
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion actions/railway-redeploy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@variablelab/railway-redeploy",
"version": "0.0.0",
"private": true,
"description": "Action to trigger a redeploy of a railway service",
"description": "Redeploys a Railway service through the Railway GraphQL API.",
"license": "MIT",
"author": "rcrd <rcrd@variable.land>",
"type": "module",
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ gh-actions takes bug reports and fixes for its actions and its reusable workflow

CI has to pass, and a maintainer squash-merges.

A merge to `main` is the release. Callers that use `@main` run the new code on their next run, and callers that pin a SHA keep theirs.
A merge to `main` is the release. Callers that use `@main` run the new code on their next run, and callers that pin an action to a SHA keep theirs. `preview-comment.yml` runs the actions at `@main`, so pinning the workflow to a SHA doesn't pin the comment code.
Loading
Loading