| Filename | Latest commit message | Latest commit date |
|---|---|---|
A skipped notification on a failure-only workflow looked exactly like a green build. GOTIFY_TOKEN is owner-level now, so the per-repo setup notes are gone too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> |
||
| action.yml | ||
| README.md | ||
ci-notify
A composite action that reports Forgejo Actions results to Gotify.
Why it exists
Forgejo 12.0.4 has no webhook event for Actions — workflow_run, workflow_job,
action_run are all rejected as unknown events, at repo level and at instance
level alike. So there is no place to configure "tell me when a build fails" once
for the whole forge.
This is the closest thing: the endpoint, the message format and the failure/success rules live here, and every workflow only adds a small job that calls it.
Usage
Add a job at the end of the workflow:
notify:
runs-on: docker
needs: [build] # every job whose result should be reported
# always(): otherwise it is skipped exactly when it matters.
# Not on pull requests: the job would hand the token to any branch a PR comes from.
if: always() && github.event_name != 'pull_request'
steps:
- uses: https://git.exithub.net/ivan.pavlina/ci-notify@main
with:
token: ${{ secrets.GOTIFY_TOKEN }}
subject: my-project
needs: ${{ toJSON(needs) }}
if: always() is the part that is easy to forget — without it the job is skipped
when an earlier job fails, which is the only case anyone actually cares about.
Staying quiet on uninteresting runs
notify_on_success decides whether a fully green run says anything. It takes an
expression, so a workflow that builds on pull requests but only deploys from
main can report deploys and stay silent otherwise:
notify_on_success: ${{ needs.deploy.result == 'success' }}
Failures always notify, regardless of this input.
Single-job workflows
When there is nothing in needs worth inspecting, pass the job status instead:
- uses: https://git.exithub.net/ivan.pavlina/ci-notify@main
if: always()
with:
token: ${{ secrets.GOTIFY_TOKEN }}
subject: my-project
status: ${{ job.status }}
Inputs
| Input | Required | Default | What |
|---|---|---|---|
token |
yes | Gotify application token — from the GOTIFY_TOKEN secret, never inline |
|
subject |
yes | Short name used in the title, e.g. mantra web |
|
needs |
no | '' |
${{ toJSON(needs) }}; any job that failed makes it a failure |
status |
no | '' |
Fallback single result when needs is not passed |
notify_on_success |
no | true |
Whether a green run notifies at all |
url |
no | http://gotify.lan |
Gotify base URL |
run_url |
no | current run | Where the notification links to |
Behaviour
| Case | Title | Priority |
|---|---|---|
any job failure / cancelled |
<subject>: <job> failed |
8 |
everything green, notify_on_success true |
<subject>: ok |
2 |
everything green, notify_on_success false |
nothing sent |
A missing token fails the notify job (the jobs it reports on keep their own result): skipping quietly would look exactly like a green run on a failure-only workflow. An unreachable Gotify only logs a warning.
Setup
GOTIFY_TOKEN is an owner-level Actions secret on ivan.pavlina, next to
REGISTRY_TOKEN, so every repo of that owner sees it without any per-repo
setup. A repo-level secret of the same name would override it.