Donavan Fritz 7a9620f9d7 render: colourise diff details + widen card, no mid-line wrap
When details is a unified diff (the network-configs notify feeds
`git diff HEAD~1`), colour each line like a pager: additions green,
deletions red, hunk headers violet, file/meta headers dim. Non-diff
details (auto-log output) still render as a plain muted block.

Also widen the card 600->760px and switch the details <pre> from
pre-wrap/word-break to white-space:pre + overflow-x:auto so diff lines
scroll instead of wrapping into mush.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 23:06:47 -05:00

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:

- 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:

- 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:

- 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):

- 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.

S
Description
Composite action: send a fritzlab-themed CI notification email via mail.fritzlab.net.
Readme 53 KiB
Languages
Python 100%