- JavaScript 79.5%
- Shell 15.7%
- Makefile 4.8%
|
Some checks are pending
test / unit (push) Waiting to run
Org migration: the action family now lives under fjord/. Repoints internal repo references (uses:, CI badges, docs, migration guides) at fjord/ and sets the action author to fjord. The old rasterstate copies are left in place. |
||
|---|---|---|
| .forgejo/workflows | ||
| src | ||
| tests | ||
| .gitignore | ||
| action.yml | ||
| CHANGELOG.md | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
Fjord Approval Gate
The deploy approval gate Forgejo doesn't have. Pause a workflow until an
authorized human approves, from the Fjord mobile app (tap to approve) or by
commenting /approve on the approval thread. Fail-closed: a timeout or /deny
stops the deploy. No github.com.
Part of the Fjord Actions
bundle. Uses fjord-notify's
relay to reach phones.
Why
Forgejo has no equivalent of GitHub's environment protection rules, so prod deploys ship the instant CI is green, with nobody in the loop. Teams hand-roll a "gate" job; when one such gate was cancelled mid-deploy it caused a ~1.5h outage. This action is the missing gate, and unlike a hosted feature you can actually self-host it.
The approval state lives in the forge (an issue + its comments). If the
runner dies while waiting, re-run with the same issue-number and it finds the
decision instead of stranding a half-applied deploy.
Usage
jobs:
deploy:
runs-on: [self-hosted, Linux]
# Queue concurrent deploys instead of cancelling a waiting one.
concurrency:
group: deploy-prod
cancel-in-progress: false
permissions:
issues: write
steps:
- uses: https://rasterhub.com/fjord/fjord-approval-gate-action@v1
with:
environment: production
approvers: stephen, ops-oncall
timeout-minutes: 30
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FJORD_RELAY_URL: ${{ vars.FJORD_RELAY_URL }} # optional: push to phones
FJORD_RELAY_TOKEN: ${{ secrets.FJORD_RELAY_TOKEN }}
- run: ./deploy.sh # only runs after approval
Approve from the Fjord app, or comment /approve (or /deny) on the issue the
action opens. /lgtm and ✅ also approve; /reject denies.
Inputs
| Input | Default | Description |
|---|---|---|
environment |
production |
Name shown in the prompt. |
approvers |
Logins allowed to approve. Empty = anyone except the run actor. | |
allow-self-approval |
false |
Let the run actor approve their own deploy. |
timeout-minutes |
60 |
Wait before timing out. |
poll-interval-seconds |
15 |
How often to check. |
fail-on-timeout |
true |
Block the deploy if no approval arrives. |
issue-number |
new issue | Reuse an approval thread (for re-runs). |
issue-title / instructions |
generated | Customize the prompt. |
relay-url / relay-token |
FJORD_RELAY_* env |
Push the request to phones. |
decisions-url |
Relay endpoint polled for an app decision (fast path). | |
token / api_url / repository |
derived | Forgejo auth + target. |
Outputs
| Output | Description |
|---|---|
approved |
true, or false on timeout when fail-on-timeout is off. |
approver |
Login of the approver. |
issue-number |
The approval thread (reuse on a re-run). |
How approval arrives
- Mobile (fast path): with
relay-urlset, the action pushes an approval-request to the Fjord relay; the app shows Approve/Deny. If you also setdecisions-url, the action polls it for the app's decision ({ "decision": "approve" | "deny", "approver": "login" }). - Comment (always works): the action opens an issue and polls its comments
for
/approveor/denyfrom an authorized approver. This needs no relay and no app, just Forgejo.
Pair with concurrency: { cancel-in-progress: false } so a second deploy queues
behind a waiting one instead of cancelling it (the "hold, don't cancel"
property that avoids the half-deploy failure mode).
License
MIT, see LICENSE.