Files
Donavan Fritz 591fb5b5d6 auto-log: fetch failing-job log from Gitea API into the details block
New optional inputs (all default to off / safe):
  - auto-log: when true and details is empty, fetch and render the run's
    failing-job log via /api/v1/repos/<repo>/actions/jobs/<id>/logs.
  - token: defaults to github.token (per-run, repo-scoped). Overridable.
  - log-lines: tail-length fallback when no ::error:: annotation present.

Selection heuristic: if any line has ::error::, return those + 12 lines of
context above each (merged windows). Otherwise the last `log-lines` lines.
Timestamp prefixes (act_runner's leading ISO-8601 + Z) are stripped.

The details block already existed; this just makes it cheap for failure
emails to surface the actual build error inline instead of forcing the
reader to click "view run →".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 14:19:32 -05:00

120 lines
4.1 KiB
Markdown

# action/notify-email
Composite Gitea Action that sends a fritzlab-themed email from a CI workflow.
Renders an HTML body (with plain-text fallback) styled to match the
`websites/fritzlab.net/theme.css` palette, and relays via `mail.fritzlab.net:25`
under the trusted-CIDR rule (no SMTP auth — see `k8s-manager` skill `mail.md`).
Gating is the caller's responsibility (typically `if: failure()`). The action
always sends when invoked.
## Usage
Minimal failure notification:
```yaml
- name: notify on failure
if: failure()
uses: https://code.fritzlab.net/action/notify-email@v1
with:
status: failure
summary: "agent deploy failed"
```
With richer context:
```yaml
- name: notify on failure
if: failure()
uses: https://code.fritzlab.net/action/notify-email@v1
with:
status: failure
subject: "agent deploy failed: ${{ github.sha }}"
summary: "Deploy of ${{ github.sha }} to bob@${{ vars.DEPLOY_HOST }} failed"
details: |
Target host: ${{ vars.DEPLOY_HOST }}
Branch: ${{ github.ref_name }}
from: agent-ci@fritzlab.net
```
Auto-include the actual build error from the failing step in the email body:
```yaml
- name: notify on failure
if: failure()
uses: https://code.fritzlab.net/action/notify-email@v1
with:
status: failure
summary: "latchkey build failed"
auto-log: 'true'
# token defaults to ${{ github.token }} which has read access to the
# current repo's actions; no caller-side config needed
```
`auto-log` fetches the run's failing-job log via the Gitea API, surfaces the
`::error::` annotation context (or the last 40 lines if there isn't one),
strips the runner's timestamp prefixes, and renders it in the details block.
Skipped if `details:` is already set (manual takes precedence).
Success notification (e.g. confirm a base-image rebuild cascaded):
```yaml
- if: success()
uses: https://code.fritzlab.net/action/notify-email@v1
with:
status: success
summary: "base #${{ github.run_number }} cascaded to runner"
```
## Inputs
| Name | Required | Default | Description |
|---|---|---|---|
| `summary` | yes | — | One-line headline rendered at the top of the email body. |
| `status` | no | `info` | `failure` / `success` / `info` — drives accent colour + subject prefix. |
| `subject` | no | `summary` | Mail subject after the status prefix. |
| `details` | no | — | Multiline preformatted block, rendered in a monospace card. |
| `auto-log` | no | `false` | When `true` and `details` is empty, fetch the failing-job log via the Gitea API and render its error context. |
| `token` | no | `${{ github.token }}` | Gitea API token used for `auto-log`. The per-run GITHUB_TOKEN normally suffices. |
| `log-lines` | no | `40` | Tail length used by `auto-log` when no `::error::` annotation is found. |
| `to` | no | `noc@fritzlab.net` | Recipient address. |
| `from` | no | `ci@fritzlab.net` | Sender address. Must be permitted by the relay. |
| `smtp-host` | no | `mail.fritzlab.net` | SMTP relay host. |
| `smtp-port` | no | `25` | SMTP port. |
## Auto-injected fields
The action reads the following from `${{ github.* }}` and includes them in
both HTML and text bodies — callers do not need to pass these:
- Repository (linked to Gitea repo page)
- Branch (`ref_name`)
- Commit (short SHA linked to commit page)
- Workflow / job
- Run number (+ attempt if `> 1`)
- Trigger (`event_name` by `actor`)
- "view run" button linking to the Actions run
## Status styling
| Status | Subject prefix | Accent |
|---|---|---|
| `failure` | `[FAILED]` | red (`#fca5a5`) |
| `success` | `[OK]` | green (`#86efac`) |
| `info` | `[INFO]` | violet (`#7c5cff`) — fritzlab default accent |
## Headers added
- `X-Fritzlab-Status: failure | success | info`
- `X-Fritzlab-Source: action/notify-email`
- `X-Fritzlab-Repo: <owner>/<repo>`
These can be used as Sieve filters in Stalwart to route or tag CI mail.
## Why HTML in a CI email
Email clients strip `<style>` blocks and `@import` and cannot fetch web fonts,
so the fritzlab palette is inlined per-element. Dark-only — fritzlab brand has
no light variant. The plain-text alternative covers terminal mail readers and
spam-filter previews.