Skip to content
Merged
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
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:

The action installs the pinned `dhq` CLI on the runner, calls `dhq deploy`, waits for the deployment to reach a terminal status, and fails the job if it didn't succeed.

> **Deploying to production?** The examples below use `@v2` for readability. `@v2` is a floating tag that moves with each v2 release — pin a commit SHA instead for any workflow holding production credentials. See [Pinning](#pinning).

## Inputs

| Name | Required | Default | Description |
Expand Down Expand Up @@ -113,6 +115,65 @@ The action installs the pinned `dhq` CLI on the runner, calls `dhq deploy`, wait
extra-args: "--copy-config --run-build"
```

## Pinning

This action receives production deploy credentials, so the ref you pin decides who can run code with them.

| Ref | Mutable? | Use when |
|---|---|---|
| `@<commit-sha>` | No — a commit SHA always names the same tree | **Recommended** for any workflow holding production secrets. |
| `@v2.0.0` | Yes — git tags can always be moved | You want a readable ref and accept that risk. |
| `@v2` | Yes, **by design** — tracks the latest v2.x.y | Non-production targets, or you accept implicit upgrades. |

`@v2` moves whenever a new v2 release ships. That is the point of a floating major tag, but it also means anyone with write access to this repository — or anyone who compromises that access — can change the code your deploy credentials run, with no review on your side. For production, pin the SHA and record the version alongside it:

```yaml
- uses: deployhq/deployhq-action@ffe9caa159b501c83cac4b70d2983078a316d15d # v2.0.0
with:
api-key: ${{ secrets.DEPLOYHQ_API_KEY }}
account: ${{ secrets.DEPLOYHQ_ACCOUNT }}
email: ${{ secrets.DEPLOYHQ_EMAIL }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
project: my-project
server: production
```

That SHA is `v2.0.0`. Don't copy it blindly once later releases exist — resolve the one you want:

```sh
gh api repos/deployhq/deployhq-action/commits/v2.0.0 --jq .sha
```

(Use the `commits` endpoint, not `git/ref/tags` — these are annotated tags, so `git/ref/tags` returns the tag object rather than the commit you need.)

### What SHA pinning does not cover

Pinning this action fixes the installer script and the default `cli-version`. It does **not** fix the bytes of the `dhq` binary: `scripts/install-cli.sh` downloads the CLI from `github.com/deployhq/deployhq-cli/releases` at run time and verifies it against a `checksums.txt` fetched from that same release. That catches a corrupted download, not someone able to replace the release assets.

If you need an immutable chain end-to-end, vendor the CLI yourself and call `dhq` directly rather than through this action. Installing `dhq` on the runner's `PATH` does **not** work — `scripts/install-cli.sh` downloads its own copy regardless and prepends that directory to `$GITHUB_PATH`. The one exception is a self-hosted runner, where you can pre-seed `$RUNNER_TOOL_CACHE/dhq/<version>/<os>_<arch>/dhq` (version without the leading `v`, e.g. `0.17.1/linux_amd64`); the installer reuses a binary already at that exact path instead of downloading.

### Bounding the blast radius

Pinning controls *what code* runs. These control *what it can reach*, and compose with it:

- Store `DEPLOYHQ_*` as **environment** secrets on a protected environment rather than repository secrets. Only a job that declares `environment: production` can request them, and they're released only once that environment's protection rules pass. The scoping alone doesn't stop another workflow from asking — the required reviewers and deployment branch policies you put on the environment are what actually gate it, so set them.
- Set `permissions: contents: read` on the job. This action needs no `GITHUB_TOKEN` scope.

### Keeping SHA pins current

Dependabot bumps SHA pins for you, rewriting both the SHA and the trailing version comment so upgrades arrive as reviewable pull requests. Merge this into your existing `.github/dependabot.yml` rather than replacing the file — clobbering it would silently disable your other ecosystems:

```yaml
version: 2
updates:
# add alongside any existing entries
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
```

This only helps if a human reads the PR — exclude this action from any Dependabot auto-merge rule, or you get `@v2`'s implicit upgrades with a SHA pin's false confidence.

## Requirements

- A DeployHQ API key (**Account Settings → API access**).
Expand Down
Loading