Skip to content
Open
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 DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Plugin releases are immutable Git tags with asset-free GitHub Releases. Before y
1. Update every `github-actions#vX.Y.Z` reference in `README.md` to the plugin version being released; the plugin linter accepts this prospective version on `main` and requires it on the tag build.
1. Wait for the Buildkite Pipelines build for `main` to pass.

The Buildkite app contract changes required for server workflow selection without an explicit selector (#33143 and #33235) are deployed. Before releasing this plugin or promoting it to `latest`, publish a compatible `buildkite-gha` release. Do not publish or promote the wrapper first; older runtimes reject selector-free configurations, and the server contract supplies the trusted trigger context that makes them valid.

When changing runtime integration, update `plugin.yml`, `hooks/command`, `.github/workflows/plugin-smoke.yml`, `tests/command.bats`, and the README together. Make sure the examples and versioned compatibility and security links describe the recommended runtime release.

From a clean, up-to-date local `main`, create the immutable lightweight tag:
Expand Down
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ During the preview, start with a simple workflow in a public `github.com` reposi

## Add workflows to a pipeline

Add the plugin to a keyed command step in your pipeline configuration. Select the workflow you want to import explicitly:
For most users, add the plugin to a keyed command step in your pipeline configuration. Select the workflow you want to import explicitly:

```yaml
steps:
Expand All @@ -24,16 +24,16 @@ steps:
workflow: .github/workflows/ci.yml
```

The selector must be an explicit path to a `.yml` or `.yaml` workflow file. When present, the file must be regular, tracked, and inside the repository. When this importer step runs, the plugin uploads one dynamic pipeline containing a Buildkite group for each directly runnable workflow. Each workflow job and static matrix entry becomes a Buildkite Pipelines job that depends on the importer step. The importer step must have a `key` and must be scheduled explicitly on either a Linux amd64 or native macOS arm64 agent. The plugin's `runners` mappings schedule generated workflow jobs only; they do not select or change the importer agent.
An explicit selector must be a path to a `.yml` or `.yaml` workflow file. When present, the file must be regular, tracked, and inside the repository. When this importer step runs, the plugin uploads one dynamic pipeline containing a Buildkite group for each directly runnable workflow. Each workflow job and static matrix entry becomes a Buildkite Pipelines job that depends on the importer step. An explicitly configured importer step must have a `key` and must be scheduled explicitly on either a Linux amd64 or native macOS arm64 agent. The plugin's `runners` mappings schedule generated workflow jobs only; they do not select or change the importer agent.

The Git ref after `github-actions#` selects the plugin code. Use a specific release such as `github-actions#v0.13.0` for an immutable pin, or use `github-actions#latest` to follow the newest stable plugin release that has passed the required validation. This is separate from the `version` property below, which selects the `buildkite-gha` runtime.

Configure runtime selection with the following properties:

| Option | Required | Default | Description |
| --- | --- | --- | --- |
| `workflow` | One of `workflow` or `workflows` | — | One explicit `.yml` or `.yaml` workflow path. Missing or untracked paths are skipped. |
| `workflows` | One of `workflow` or `workflows` | — | Non-empty array of explicit `.yml` or `.yaml` workflow paths. Missing or untracked paths are skipped. |
| `workflow` | Explicit selection only: one of `workflow` or `workflows` | — | One explicit `.yml` or `.yaml` workflow path. Missing or untracked paths are skipped. |
| `workflows` | Explicit selection only: one of `workflow` or `workflows` | — | Non-empty array of explicit `.yml` or `.yaml` workflow paths. Missing or untracked paths are skipped. |
| `version` | No | `latest` | Latest stable or an exact `buildkite-gha` release from `0.9.0` onward. |
| `source-ref` | No | — | Full `buildkite-gha` source commit to build for development testing; mutually exclusive with `version`. |
| `minimum-release-age` | No | `0s` | Minimum release age used by mise when resolving `latest`. |
Expand All @@ -46,7 +46,7 @@ Configure runtime selection with the following properties:

To test unreleased runtime behavior, set `source-ref` to a full lowercase 40-character commit from the public `buildkite/buildkite-gha` repository and omit `version`. The plugin uses mise and Go 1.26.5 to build Linux amd64 and Darwin arm64 executables from that exact source, runs the executable native to the importer agent, and supplies the counterpart to generated jobs. Source commits are for development only and do not use release checksums, attestations, or `minimum-release-age`.

The plugin schema requires exactly one of `workflow` or `workflows` and validates its explicit paths, the runtime-acquisition fields `version`, `source-ref`, and `minimum-release-age`, the boolean `experimental-runner-user` field, and the admission-level shape of `oidc`. It passes behavioral configuration through to the selected `buildkite-gha` runtime, which validates the complete configuration strictly. This allows runtime releases to extend the supported syntax without requiring a companion plugin release.
The plugin schema validates explicit selector paths when present, the runtime-acquisition fields `version`, `source-ref`, and `minimum-release-age`, the boolean `experimental-runner-user` field, and the admission-level shape of `oidc`. It passes behavioral configuration through to the selected `buildkite-gha` runtime, which validates the complete configuration strictly. This allows runtime releases to extend the supported syntax without requiring a companion plugin release.

### Select workflows

Expand All @@ -68,7 +68,7 @@ plugins:
- .github/workflows/release.yml
```

Configure exactly one selector form. Each present value must identify one regular, tracked `.yml` or `.yaml` file inside the repository. Empty values and arrays, directories, globs, symlinks, files outside the repository, and wildcard selectors are not accepted. Selected paths are canonicalized, sorted, and deduplicated before upload.
For explicit selection, configure exactly one selector form. Each present value must identify one regular, tracked `.yml` or `.yaml` file inside the repository. Empty values and arrays, directories, globs, symlinks, files outside the repository, and wildcard selectors are not accepted. Selected paths are canonicalized, sorted, and deduplicated before upload.

Missing or untracked configured paths produce a warning and are skipped. If all configured paths are missing or untracked, the importer succeeds without uploading a pipeline. Remaining workflows are compiled and uploaded in one pipeline transaction. Workflow groups use the workflow's `name`, falling back to its repository path; a supported non-empty `run-name` is appended to the group label. Reusable workflows whose only trigger is `workflow_call` do not create groups, but remain available to matched callers. Selecting only reusable workflows is an error. A safely reportable compilation or trigger-translation error in one workflow instead becomes a failing top-level step, allowing other selected workflows to remain in the uploaded pipeline.

Expand Down Expand Up @@ -245,6 +245,20 @@ For manual and scheduled builds, the plugin finds the exact commit from the chec

Pull request builds receive `pull_request` context. Branch and tag builds receive `push` context. Verified linked merge queue and release webhooks supply `merge_group` and `release` context. Buildkite scheduled builds select workflows with a `schedule` trigger, while manual UI or API builds select workflows with `workflow_dispatch`; dispatch inputs are not available.

### Run from a GitHub Actions Pipeline Trigger

> [!NOTE]
> GitHub Actions Pipeline Triggers are in private preview and feature flagged off for most organizations.

When this trigger type is enabled, the Buildkite app and `buildkite-gha` select the workflow associated with the trigger. The minimal pipeline configuration is:

```yaml
steps:
- plugin: github-actions
```

Supported runtime and behavioral options may still be configured using the standard `plugins` form while omitting both `workflow` and `workflows`; the plugin forwards them without inferring trigger context.

## Configure checkout and credentials

Supported, audited `actions/checkout` revisions can check out the event repository at its event commit or a static branch. Checkout runs anonymously when repository-provider credentials are not enabled. Private checkout uses Buildkite repository-provider Git credentials when they are enabled and authorized for the job. Direct and recursive GitHub submodules are supported within the compatibility guide's transport and credential boundaries.
Expand Down
7 changes: 7 additions & 0 deletions plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,14 @@ requirements:
- mktemp
- cp
configuration:
type: object
oneOf:
- not:
anyOf:
- required:
- workflow
- required:
- workflows
- required:
- workflow
- required:
Expand Down
33 changes: 33 additions & 0 deletions tests/command.bats
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ if [[ "\${1:-}" == --no-config && "\${2:-}" == exec && "\${4:-}" == -- && "\${5:
echo 'buildkite-gha: plugin: BUILDKITE_PLUGIN_CONFIGURATION is required' >&2
exit 2
fi
if [[ -n "\${MOCK_IMPORTER_ERROR:-}" ]]; then
echo "\$MOCK_IMPORTER_ERROR" >&2
fi
exit "\${MOCK_IMPORTER_EXIT:-0}"
fi
if [[ "\${1:-}" == --no-config && "\${2:-}" == exec && "\${3:-}" == go@1.26.5 && "\${4:-}" == -- && "\${5:-}" == env && "\${6:-}" == -u && "\${7:-}" == GOBIN && "\${8:-}" == CGO_ENABLED=0 && "\${9:-}" == GOTOOLCHAIN=local ]]; then
Expand Down Expand Up @@ -163,6 +166,36 @@ teardown() { rm -rf "$TMP"; }
grep -Fx "cwd=$PWD" "$MOCK_LOG"
}

@test "passes an empty configuration object to buildkite-gha unchanged" {
export BUILDKITE_PLUGIN_CONFIGURATION='{}'
run "$REPO/hooks/command"
[ "$status" -eq 0 ] || { echo "$output"; false; }
grep -Fx 'mise=--no-config exec github:buildkite/buildkite-gha@latest -- buildkite-gha plugin' "$MOCK_LOG"
grep -Fx 'configuration={}' "$MOCK_LOG"
}

@test "passes selector-free runtime and behavioral options to buildkite-gha unchanged" {
export BUILDKITE_PLUGIN_GITHUB_ACTIONS_VERSION=v0.35.1
export BUILDKITE_PLUGIN_GITHUB_ACTIONS_MINIMUM_RELEASE_AGE=24h
export BUILDKITE_PLUGIN_CONFIGURATION='{"version":"v0.35.1","minimum-release-age":"24h","experimental-runner-user":false,"runners":[{"runs-on":"ubuntu-latest","queue":"hosted"}],"oidc":{"claims":["organization_id"],"subject-claim":"pipeline_id"}}'
run "$REPO/hooks/command"
[ "$status" -eq 0 ] || { echo "$output"; false; }
grep -Fx 'mise=--no-config exec github:buildkite/buildkite-gha@0.35.1 -- buildkite-gha plugin' "$MOCK_LOG"
grep -Fx 'minimum-release-age=24h' "$MOCK_LOG"
grep -Fx "configuration=$BUILDKITE_PLUGIN_CONFIGURATION" "$MOCK_LOG"
}

@test "leaves ordinary selector-free failure to buildkite-gha" {
export BUILDKITE_PLUGIN_GITHUB_ACTIONS_VERSION=v0.35.1
export BUILDKITE_PLUGIN_CONFIGURATION='{"version":"v0.35.1","runners":[{"runs-on":"ubuntu-latest","queue":"hosted"}]}'
export MOCK_IMPORTER_EXIT=2
export MOCK_IMPORTER_ERROR='buildkite-gha: plugin: workflow or workflows is required outside a GitHub Actions Pipeline Trigger build'
run "$REPO/hooks/command"
[ "$status" -eq 2 ]
[[ "$output" == *"$MOCK_IMPORTER_ERROR"* ]]
grep -Fx "configuration=$BUILDKITE_PLUGIN_CONFIGURATION" "$MOCK_LOG"
}

@test "keeps mise acquisition failures visible in quiet mode" {
export MOCK_MISE_ACQUISITION_FAILURE=1
run "$REPO/hooks/command"
Expand Down