fix(remediation): link ntfy follow-ups to Forgejo work #169

Merged
nimmo merged 6 commits from fix/remediation-follow-up-notifications into main 2026-08-13 19:56:25 +01:00
Owner

Summary

  • publish a bounded remediation issue/PR report from the controller
  • send a separate post-publication ntfy follow-up with direct Forgejo links
  • retain the Automated Update Remediation milestone and keep ntfy secrets out of the model-capable job
  • normalize live Forgejo JSON issue indices before producing the report

Validation

  • ./tests/nixos-update-remediation-regressions.sh
  • Forgejo workflow lint with actionlint
  • git diff --check

Rollout

No NixOS deployment is required. Once merged, the next update-mode workflow with published remediation will send the additional ntfy follow-up.

Refs #168

## Summary - publish a bounded remediation issue/PR report from the controller - send a separate post-publication ntfy follow-up with direct Forgejo links - retain the `Automated Update Remediation` milestone and keep ntfy secrets out of the model-capable job - normalize live Forgejo JSON issue indices before producing the report ## Validation - `./tests/nixos-update-remediation-regressions.sh` - Forgejo workflow lint with `actionlint` - `git diff --check` ## Rollout No NixOS deployment is required. Once merged, the next update-mode workflow with published remediation will send the additional ntfy follow-up. Refs #168
nimmo self-assigned this 2026-08-13 19:04:04 +01:00
fix(remediation): notify Forgejo follow-ups
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 1m21s
Build and Push Attic Cache / build (pull_request) Has been skipped
Build and Push Attic Cache / pin-lifecycle (pull_request) Has been skipped
Build and Push Attic Cache / remediate (pull_request) Has been skipped
Build and Push Attic Cache / notify-remediation (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 5m2s
a1be00de25
Refs #168
Author
Owner

Automated code review

Reviewed commit: 4baab2c3b332c13bc505afbaa3ddf1b20dd1b073

Verdict: Ready to merge

No blocking or important findings were retained, and deterministic checks passed. Suggestions remain advisory.

Overall assessment

The pull request successfully decouples ntfy notifications from the model-capable remediation job, introduces a bounded public issue/PR report via a new notify-remediation workflow step, and normalizes Forgejo JSON issue indices in the Python controller. Validation includes regression tests, actionlint, and diff checks. The changes align with security boundaries by keeping ntfy secrets out of the model sandbox and correctly migrate GitHub Actions output variables to Forgejo's native FORGEJO_OUTPUT.

Blocking findings

None.

Important findings

None.

Suggestions

  • Bash empty array expansion safety under set -u (.forgejo/workflows/attic-cache.yml:398; medium confidence)
    curl_args=() followed by "${curl_args[@]}" inside a step with set -eu enabled.
    Impact: Bash versions prior to 4.4 trigger an unbound variable error when expanding an empty array with set -u, potentially aborting the notification step.
    Suggested fix: Guard the expansion with a length check (e.g., if [ ${#curl_args[@]} -gt 0 ]; then) or use the POSIX-safe pattern "${curl_args[@]+"${curl_args[@]}"}" to ensure compatibility across runner environments.

Tests and validation

  • No configured deterministic checks.

Questions

  • Does the target ntfy instance version support raw newline characters in --data-raw payloads without truncation or encoding normalization, given that $message is constructed with literal newlines?

Review limitations

  • Review is based solely on the provided diff and repository context; cannot execute workflow runs, validate Forgejo output variable resolution in the actual runner environment, or verify runtime ntfy payload delivery.
  • Cannot assess cross-host deployment impact or live auto-update behavior without access to the running NixOS configuration or CI logs.

Diff coverage

  • .forgejo/workflows/attic-cache.yml: reviewed — included in a context-limited batch
  • README.md: reviewed — included in a context-limited batch
  • scripts/auto-update-workflow-route.sh: reviewed — included in a context-limited batch
  • scripts/nixos-update-remediation.py: reviewed — included in a context-limited batch
  • tests/nixos-update-remediation-integration.py: reviewed — included in a context-limited batch
  • tests/nixos-update-remediation-regressions.sh: reviewed — included in a context-limited batch
Review metadata
  • Reviewer: forgejo-ai-review v1
  • Model: qwen3.6:35b-a3b-q8_0
  • Guidance loaded: .forgejo/ai-review.md, .forgejo/ai-review.yml, AGENTS.md, README.md
  • Commits considered: 6
  • Previous automated review: updated
  • Findings: 1
<!-- forgejo-ai-review:v1 --> ## Automated code review Reviewed commit: `4baab2c3b332c13bc505afbaa3ddf1b20dd1b073` ## Verdict: Ready to merge No blocking or important findings were retained, and deterministic checks passed. Suggestions remain advisory. ### Overall assessment The pull request successfully decouples ntfy notifications from the model-capable remediation job, introduces a bounded public issue/PR report via a new `notify-remediation` workflow step, and normalizes Forgejo JSON issue indices in the Python controller. Validation includes regression tests, actionlint, and diff checks. The changes align with security boundaries by keeping ntfy secrets out of the model sandbox and correctly migrate GitHub Actions output variables to Forgejo's native `FORGEJO_OUTPUT`. ### Blocking findings None. ### Important findings None. ### Suggestions - **Bash empty array expansion safety under set -u** (.forgejo/workflows/attic-cache.yml:398; medium confidence) curl_args=() followed by "${curl_args[@]}" inside a step with set -eu enabled. Impact: Bash versions prior to 4.4 trigger an unbound variable error when expanding an empty array with set -u, potentially aborting the notification step. Suggested fix: Guard the expansion with a length check (e.g., if [ ${#curl_args[@]} -gt 0 ]; then) or use the POSIX-safe pattern "${curl_args[@]+"${curl_args[@]}"}" to ensure compatibility across runner environments. ### Tests and validation - No configured deterministic checks. ### Questions - Does the target ntfy instance version support raw newline characters in --data-raw payloads without truncation or encoding normalization, given that $message is constructed with literal newlines? ### Review limitations - Review is based solely on the provided diff and repository context; cannot execute workflow runs, validate Forgejo output variable resolution in the actual runner environment, or verify runtime ntfy payload delivery. - Cannot assess cross-host deployment impact or live auto-update behavior without access to the running NixOS configuration or CI logs. ### Diff coverage - `.forgejo/workflows/attic-cache.yml`: **reviewed** — included in a context-limited batch - `README.md`: **reviewed** — included in a context-limited batch - `scripts/auto-update-workflow-route.sh`: **reviewed** — included in a context-limited batch - `scripts/nixos-update-remediation.py`: **reviewed** — included in a context-limited batch - `tests/nixos-update-remediation-integration.py`: **reviewed** — included in a context-limited batch - `tests/nixos-update-remediation-regressions.sh`: **reviewed** — included in a context-limited batch <details><summary>Review metadata</summary> - Reviewer: forgejo-ai-review v1 - Model: qwen3.6:35b-a3b-q8_0 - Guidance loaded: .forgejo/ai-review.md, .forgejo/ai-review.yml, AGENTS.md, README.md - Commits considered: 6 - Previous automated review: updated - Findings: 1 </details>
fix(remediation): preserve partial follow-up reports
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 1m20s
Build and Push Attic Cache / build (pull_request) Has been skipped
Build and Push Attic Cache / pin-lifecycle (pull_request) Has been skipped
Build and Push Attic Cache / remediate (pull_request) Has been skipped
Build and Push Attic Cache / notify-remediation (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 5m1s
3d683f2ee7
Refs #168
Author
Owner

Responding to the automated review:

  • Accepted the defensive JSON-handling suggestion. 3d683f2 validates the atomic report with jq -ce; malformed output is logged and replaced with an empty report, so no ntfy follow-up is sent.
  • The requested scan_status == 0 guard is intentionally not applied. The controller writes the report atomically only after its bounded scan loop. A non-zero exit can therefore follow successful publication for earlier incidents; suppressing those verified links would hide the manual follow-up that the notification is meant to surface. Each workflow run uses a new mktemp report path, so the report cannot be stale from a prior run.

Revalidated with ./tests/nixos-update-remediation-regressions.sh, actionlint, and git diff --check.

Responding to the automated review: - Accepted the defensive JSON-handling suggestion. `3d683f2` validates the atomic report with `jq -ce`; malformed output is logged and replaced with an empty report, so no ntfy follow-up is sent. - The requested `scan_status == 0` guard is intentionally not applied. The controller writes the report atomically only after its bounded scan loop. A non-zero exit can therefore follow successful publication for earlier incidents; suppressing those verified links would hide the manual follow-up that the notification is meant to surface. Each workflow run uses a new `mktemp` report path, so the report cannot be stale from a prior run. Revalidated with `./tests/nixos-update-remediation-regressions.sh`, actionlint, and `git diff --check`.
Author
Owner

Review response before the follow-up push:

  • I will accept the ntfy payload hardening: construct real newline-separated text and pass it with printf %s / curl --data-raw so backslashes in public URLs are preserved literally.
  • I will also trim a string index before decimal validation; this is a harmless robustness improvement.
  • I am rejecting the proposed downgrade of publication_report_record validation failures. A state marked published but lacking a valid public issue/PR reference is an integrity violation in the cross-job hand-off. Failing the scan is intentional fail-closed behavior; logging and continuing would lose required follow-up work.

I will rerun the remediation regressions, workflow lint, and diff check before pushing the resulting commit.

Review response before the follow-up push: - I will accept the ntfy payload hardening: construct real newline-separated text and pass it with `printf %s` / `curl --data-raw` so backslashes in public URLs are preserved literally. - I will also trim a string index before decimal validation; this is a harmless robustness improvement. - I am rejecting the proposed downgrade of `publication_report_record` validation failures. A state marked published but lacking a valid public issue/PR reference is an integrity violation in the cross-job hand-off. Failing the scan is intentional fail-closed behavior; logging and continuing would lose required follow-up work. I will rerun the remediation regressions, workflow lint, and diff check before pushing the resulting commit.
fix(remediation): preserve notification URLs
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 1m17s
Build and Push Attic Cache / build (pull_request) Has been skipped
Build and Push Attic Cache / pin-lifecycle (pull_request) Has been skipped
Build and Push Attic Cache / remediate (pull_request) Has been skipped
Build and Push Attic Cache / notify-remediation (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 3m56s
aaf5419dd5
Refs #168
Author
Owner

Review response before the next push:

Accepted. The notifier intentionally uses Bash array and string features, so I will set shell: bash explicitly on that step rather than relying on runner defaults. I will extend the workflow regression assertion, rerun the remediation suite, actionlint, and diff check, then push.

Review response before the next push: Accepted. The notifier intentionally uses Bash array and string features, so I will set `shell: bash` explicitly on that step rather than relying on runner defaults. I will extend the workflow regression assertion, rerun the remediation suite, actionlint, and diff check, then push.
fix(remediation): declare notifier shell
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 1m20s
Build and Push Attic Cache / build (pull_request) Has been skipped
Build and Push Attic Cache / pin-lifecycle (pull_request) Has been skipped
Build and Push Attic Cache / remediate (pull_request) Has been skipped
Build and Push Attic Cache / notify-remediation (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 4m53s
e34ae367ed
Refs #168
Author
Owner

Review response before the next push:

  • Accepted: report-validation failures will include the incident fingerprint and published status, while retaining fail-closed behavior.
  • Accepted: I will assert that the compact JSON output contains no literal newline before writing GITHUB_OUTPUT.
  • Rejected: the integration test’s exact fake URL is intentional protocol coverage. It verifies that the controller carries the Forgejo URL returned by Tea into the bounded report; a broad URL regex would weaken that contract and conceal a producer/consumer mismatch.

I will run the remediation regressions, workflow lint, and diff check before pushing.

Review response before the next push: - Accepted: report-validation failures will include the incident fingerprint and published status, while retaining fail-closed behavior. - Accepted: I will assert that the compact JSON output contains no literal newline before writing `GITHUB_OUTPUT`. - Rejected: the integration test’s exact fake URL is intentional protocol coverage. It verifies that the controller carries the Forgejo URL returned by Tea into the bounded report; a broad URL regex would weaken that contract and conceal a producer/consumer mismatch. I will run the remediation regressions, workflow lint, and diff check before pushing.
fix(remediation): diagnose invalid follow-up reports
Some checks failed
Build and Push Attic Cache / test (pull_request) Successful in 1m19s
Build and Push Attic Cache / pin-lifecycle (pull_request) Has been skipped
Build and Push Attic Cache / build (pull_request) Has been skipped
Build and Push Attic Cache / remediate (pull_request) Has been skipped
Build and Push Attic Cache / notify-remediation (pull_request) Has been skipped
AI pull-request review / review (pull_request) Has been cancelled
caae61b258
Refs #168
refactor(ci): use Forgejo output files
All checks were successful
Build and Push Attic Cache / test (pull_request) Successful in 1m19s
Build and Push Attic Cache / build (pull_request) Has been skipped
Build and Push Attic Cache / pin-lifecycle (pull_request) Has been skipped
Build and Push Attic Cache / remediate (pull_request) Has been skipped
Build and Push Attic Cache / notify-remediation (pull_request) Has been skipped
AI pull-request review / review (pull_request) Successful in 4m7s
4baab2c3b3
Refs #168
Author
Owner

Final readiness summary:

  • Automated review of 4baab2c is Ready to merge with no blocking or important findings.
  • The remaining empty-array note is advisory; this notifier explicitly runs under Bash on the NixOS runner, where the empty-array expansion is supported.
  • Validation passed: ./tests/nixos-update-remediation-regressions.sh, actionlint, and git diff --check.
  • No live deployment is required; once merged, the next update-mode remediation publication will emit the new issue/PR follow-up notification.

The PR is ready for merge approval.

Final readiness summary: - Automated review of `4baab2c` is **Ready to merge** with no blocking or important findings. - The remaining empty-array note is advisory; this notifier explicitly runs under Bash on the NixOS runner, where the empty-array expansion is supported. - Validation passed: `./tests/nixos-update-remediation-regressions.sh`, actionlint, and `git diff --check`. - No live deployment is required; once merged, the next update-mode remediation publication will emit the new issue/PR follow-up notification. The PR is ready for merge approval.
nimmo merged commit 999961b155 into main 2026-08-13 19:56:25 +01:00
nimmo deleted branch fix/remediation-follow-up-notifications 2026-08-13 19:56:26 +01:00
Sign in to join this conversation.
No reviewers
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
nimmo/nixos-config!169
No description provided.