From c463aafd90a76279ed813ad3eae1491aa321e186 Mon Sep 17 00:00:00 2001 From: kurok <22548029+kurok@users.noreply.github.com> Date: Thu, 2 Jul 2026 22:18:01 +0100 Subject: [PATCH] docs: add CHANGELOG and cut v4.0.0 docs (bump examples to @v4) Adds CHANGELOG.md documenting the 4.0.0 capability wave (features #50-#59) and its breaking changes (ec2:CreateTags now always required; cleanup-on-start-failure defaults to terminate; DeleteOnTermination forced). Updates all README/docs/example usage snippets from @v3 to @v4 and adds a Changelog pointer. Signed-off-by: kurok <22548029+kurok@users.noreply.github.com> --- CHANGELOG.md | 72 ++++++++++++++++++++++++++++++++++++ README.md | 28 ++++++++------ docs/cleanup-workflow.yml | 2 +- examples/user-data/README.md | 2 +- 4 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..f2a6ca5b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,72 @@ +# Changelog + +All notable changes to this action are documented here. This project follows +[Semantic Versioning](https://semver.org/). The moving major tag (e.g. `v4`) +always points at the latest release in that major line. + +## [4.0.0] - 2026-07-02 + +A capability wave across cost, reliability, reach, and toil. 10 features, each +shipped as its own PR (#50–#59). + +### ⚠️ Breaking changes + +- **`ec2:CreateTags` is now always required.** Every launched instance (and its + volumes) is stamped with the action's signature tags — `ec2-github-runner:managed`, + `:repository`, `:label`, `:started-at` — which the cleanup reaper relies on. + Grant `ec2:CreateTags` with the condition `ec2:CreateAction = RunInstances` + (see the README permissions policy) or `RunInstances` will be denied. Previously + this permission was only needed when using `aws-resource-tags`. (#42, #45) +- **`cleanup-on-start-failure` defaults to `true`.** When a runner fails to + bootstrap or register, the action now captures the instance's console output and + **terminates** it, instead of leaving it running after a registration timeout. + Set `cleanup-on-start-failure: false` to preserve the old keep-it-running + behavior for interactive debugging. (#41) +- The root EBS volume created for `encrypt-ebs` / `volume-*` now always sets + `DeleteOnTermination: true`, so resized/encrypted volumes never leak with the + ephemeral instance. (#44) + +### Added + +- **Bootstrap diagnostics** (#41): per-phase `ec2-github-runner:bootstrap` + phone-home tags, fast-fail on `failed:` (naming the step), console-output + capture on failure (token redacted), and `cleanup-on-start-failure`. +- **Orphan protection** (#42): `max-lifetime-minutes` TTL self-destruct and a new + `mode: cleanup` reaper (with `max-age-minutes`, `dry-run`) that terminates + leaked instances this action started in the repo. Example scheduled workflow in + `docs/cleanup-workflow.yml`. +- **Root volume configuration** (#44): `volume-size`, `volume-type`, `volume-iops`, + `volume-throughput` — composes with `encrypt-ebs`. +- **Capacity resilience** (#40): `ec2-instance-type` and `subnet-id` accept + comma-separated ordered fallback lists (subnet/AZ first, then type). New outputs + `instance-type-used`, `subnet-id-used`. +- **Spot instances** (#39): `market-type: spot` with `spot-fallback` and + `spot-max-price`; composes with capacity fallback. New output `market-type-used`. +- **Automated runner-version bumps** (#47): `scripts/bump-runner.js` (manual or + via the weekly `Bump actions/runner` workflow) updates the checksum table, + defaults, docs, and dist, then opens a no-auto-merge PR. +- **ARM64/Graviton support** (#43): `architecture: arm64`, with AMI-architecture + validation that fails fast on a mismatch. +- **Multi-runner batches** (#45): `count` (with `allow-partial`) launches N runners + behind one label for matrix builds. New output `ec2-instance-ids` (JSON array); + `stop` accepts `ec2-instance-ids`. +- **Pluggable bootstrap** (#46): `pre-runner-script` (inject steps into the built-in + bootstrap) and `user-data-template` (full override with `{{PLACEHOLDER}}` + rendering). Community-maintained Ubuntu example in `examples/user-data/`. +- **Warm pools** (#48): `reuse: stop` reuses stopped instances (stop/start) for + much faster job starts, with `reuse-pool-tag`, `reuse-max-cycles`, and reaper + draining via `reaper-stopped-max-age`. See the security note — reuse carries disk + state between jobs and is unsafe for public/untrusted-PR repos. + +### IAM + +- Base policy additionally needs `ec2:DescribeTags` and `ec2:GetConsoleOutput` + (diagnostics + reaper). The runner's own instance role (`iam-role-name`) may be + granted self-scoped `ec2:CreateTags` for the optional bootstrap phone-home. + +### Internal + +- Unit-test suite grew from 52 to 224 tests; lint, `verify-dist`, and the pinned + runner checksum verification stay green on every PR. + +Earlier releases: https://github.com/namecheap/ec2-github-runner/releases diff --git a/README.md b/README.md index d626b24d..67926e16 100644 --- a/README.md +++ b/README.md @@ -386,7 +386,7 @@ jobs: aws-region: ${{ secrets.AWS_REGION }} - name: Start EC2 runner id: start-ec2-runner - uses: namecheap/ec2-github-runner@v3 + uses: namecheap/ec2-github-runner@v4 with: mode: start github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} @@ -422,7 +422,7 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ secrets.AWS_REGION }} - name: Stop EC2 runner - uses: namecheap/ec2-github-runner@v3 + uses: namecheap/ec2-github-runner@v4 with: mode: stop github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} @@ -444,14 +444,14 @@ Set `reuse: stop` on **both** the start and stop steps: ```yml # start -- uses: namecheap/ec2-github-runner@v3 +- uses: namecheap/ec2-github-runner@v4 with: mode: start reuse: stop reuse-pool-tag: ci-medium # instances are interchangeable within a pool tag # ... other inputs ... # stop -- uses: namecheap/ec2-github-runner@v3 +- uses: namecheap/ec2-github-runner@v4 with: mode: stop reuse: stop @@ -485,7 +485,7 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ secrets.AWS_REGION }} - id: start - uses: namecheap/ec2-github-runner@v3 + uses: namecheap/ec2-github-runner@v4 with: mode: start github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} @@ -514,7 +514,7 @@ jobs: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ secrets.AWS_REGION }} - - uses: namecheap/ec2-github-runner@v3 + - uses: namecheap/ec2-github-runner@v4 with: mode: stop github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} @@ -530,7 +530,7 @@ CI runners are a textbook spot workload — short-lived, ephemeral (registered w ```yml - name: Start EC2 runner - uses: namecheap/ec2-github-runner@v3 + uses: namecheap/ec2-github-runner@v4 with: mode: start # ... other inputs ... @@ -549,7 +549,7 @@ A single `subnet-id` + `ec2-instance-type` means a single point of failure: when ```yml - name: Start EC2 runner - uses: namecheap/ec2-github-runner@v3 + uses: namecheap/ec2-github-runner@v4 with: mode: start # ... other inputs ... @@ -570,7 +570,7 @@ Need an extra package or a different distro? Two escape hatches mean you never h Inject shell into the built-in (supported) bootstrap, run as root before the runner registers: ```yml -- uses: namecheap/ec2-github-runner@v3 +- uses: namecheap/ec2-github-runner@v4 with: mode: start # ... other inputs ... @@ -586,7 +586,7 @@ It runs under `set -euo pipefail` and a failure is tagged `failed:pre-runner-scr Replace the bootstrap entirely with your own script (repo-relative path or inline string). The action substitutes documented placeholders and submits the result: ```yml -- uses: namecheap/ec2-github-runner@v3 +- uses: namecheap/ec2-github-runner@v4 with: mode: start # ... other inputs ... @@ -612,7 +612,7 @@ Graviton instances (c7g/m7g/r7g/…) deliver ~20–40% better price/performance ```yml - name: Start EC2 runner - uses: namecheap/ec2-github-runner@v3 + uses: namecheap/ec2-github-runner@v4 with: mode: start architecture: arm64 @@ -630,7 +630,7 @@ The runner inherits the AMI's root volume size — 8 GiB on Amazon Linux 2023. D ```yml - name: Start EC2 runner - uses: namecheap/ec2-github-runner@v3 + uses: namecheap/ec2-github-runner@v4 with: mode: start # ... other inputs ... @@ -717,6 +717,10 @@ Please find more details about this security note on [GitHub documentation](http > ⚠️ **`reuse: stop` (warm pools) makes this worse.** With reuse, a runner's disk carries over between jobs, so a later job can read a previous job's residue (checked-out code, caches, credentials written to disk). Only use `reuse: stop` for a **single trusted repository's** CI. Never combine it with public-repo / untrusted-PR workloads. The default `reuse: terminate` gives every job a fresh instance. +## Changelog + +See [CHANGELOG.md](CHANGELOG.md) for release notes and breaking changes. Pin the moving major tag (`@v4`) for the latest release in that line, or a specific version (`@v4.0.0`) to pin exactly. + ## License Summary This code is made available under the [MIT license](LICENSE). diff --git a/docs/cleanup-workflow.yml b/docs/cleanup-workflow.yml index 20e0ebb6..195d5eaf 100644 --- a/docs/cleanup-workflow.yml +++ b/docs/cleanup-workflow.yml @@ -31,7 +31,7 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ secrets.AWS_REGION }} - name: Reap leaked runners - uses: namecheap/ec2-github-runner@v3 + uses: namecheap/ec2-github-runner@v4 with: mode: cleanup github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} diff --git a/examples/user-data/README.md b/examples/user-data/README.md index 28de6b1c..3bec7032 100644 --- a/examples/user-data/README.md +++ b/examples/user-data/README.md @@ -5,7 +5,7 @@ ## Using a template ```yml -- uses: namecheap/ec2-github-runner@v3 +- uses: namecheap/ec2-github-runner@v4 with: mode: start github-token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}