Managed hook block drops actionlint -config-file, breaking Forgejo repos with custom runner labels #984

Closed
opened 2026-08-09 05:29:30 +00:00 by coilyco-ops · 1 comment
Member

Problem

managed_block() in scripts/apply-agentic-os-hooks.py emits the actionlint hook without -config-file. For a repo whose workflows live in .forgejo/workflows and which declares a custom self-hosted runner label, that turns a green repo red on the next apply.

Reproduced in coilyco-flight-deck/agent-compose while bumping v0.253.0 to aos-precommit-v0.16.0:

.forgejo/workflows/release.yml:32:14: label "docker" is unknown ... if it is a
custom label for self-hosted runner, set list of labels in actionlint.yaml
config file [runner-label]

The repo has a correct .github/actionlint.yaml declaring the docker label. Verified directly against the hook's own actionlint binary:

  • actionlint .forgejo/workflows/release.yml fails with the label error.
  • actionlint -config-file .github/actionlint.yaml .forgejo/workflows/release.yml passes.

So the config is not auto-discovered. actionlint resolves its config relative to a detected project, and detection keys off .github/workflows, which a Forgejo-only repo does not have. The dropped flag is load-bearing for exactly the repos this hook set targets.

Impact

Any consumer with Forgejo workflows plus a custom runner label. The failure appears only after the managed block is re-applied, and the obvious local fix, editing the block, is silently reverted by the next apply.

Fix

Emit the flag from the template when the consumer has .github/actionlint.yaml, or emit it unconditionally and let actionlint ignore a missing file. Either keeps the block authoritative, which a per-repo hand-edit does not.

Current state

agent-compose carries the flag as a marked local deviation pointing at this issue, so it stays green until the template is fixed. That comment should be removed when it is.

## Problem `managed_block()` in `scripts/apply-agentic-os-hooks.py` emits the actionlint hook without `-config-file`. For a repo whose workflows live in `.forgejo/workflows` and which declares a custom self-hosted runner label, that turns a green repo red on the next apply. Reproduced in `coilyco-flight-deck/agent-compose` while bumping `v0.253.0` to `aos-precommit-v0.16.0`: ``` .forgejo/workflows/release.yml:32:14: label "docker" is unknown ... if it is a custom label for self-hosted runner, set list of labels in actionlint.yaml config file [runner-label] ``` The repo has a correct `.github/actionlint.yaml` declaring the `docker` label. Verified directly against the hook's own actionlint binary: * `actionlint .forgejo/workflows/release.yml` fails with the label error. * `actionlint -config-file .github/actionlint.yaml .forgejo/workflows/release.yml` passes. So the config is not auto-discovered. actionlint resolves its config relative to a detected project, and detection keys off `.github/workflows`, which a Forgejo-only repo does not have. The dropped flag is load-bearing for exactly the repos this hook set targets. ## Impact Any consumer with Forgejo workflows plus a custom runner label. The failure appears only after the managed block is re-applied, and the obvious local fix, editing the block, is silently reverted by the next apply. ## Fix Emit the flag from the template when the consumer has `.github/actionlint.yaml`, or emit it unconditionally and let actionlint ignore a missing file. Either keeps the block authoritative, which a per-repo hand-edit does not. ## Current state `agent-compose` carries the flag as a marked local deviation pointing at this issue, so it stays green until the template is fixed. That comment should be removed when it is.
Author
Member

Fixed in 770daf10 on main.

managed_block() now emits the flag, gated on the consumer actually shipping .github/actionlint.yaml:

      - id: actionlint
        args:
          - -config-file
          - .github/actionlint.yaml
        files: ^\.forgejo/workflows/.*\.(ya?ml)$

Conditional rather than unconditional, and the issue's second option is not safe: actionlint exits 3 on a config path it cannot read, not silently.

$ actionlint -config-file .github/does-not-exist.yaml .forgejo/workflows/ci.yml
could not read config file ".github/does-not-exist.yaml": open ...: no such file or directory
exit=3

An always-on flag would turn every consumer without a config red, trading one broken class for a larger one.

Shape of the fix:

  • ACTIONLINT_CONFIG_REL plus actionlint_args(repo_dir) decide emission per consumer.
  • managed_block() and empty_config_template() take an optional repo_dir. upsert_managed_block() derives it from config_path.parent, so the create and refresh paths both carry it.
  • Two tests: one parsing the rendered block and asserting the args appear only with the config present, one driving a real apply plus refresh so the flag survives a block rewrite.

Verified the rendered block passes pre-commit validate-config, and that actionlint accepts a Forgejo-only layout with the flag and rejects it without.

On the current state note: agent-compose carries args: [-config-file, .github/actionlint.yaml] on the actionlint hook with no marker comment attached, so there is nothing to remove there. Its next apply will re-emit the same flag from the template.

Fixed in `770daf10` on `main`. `managed_block()` now emits the flag, gated on the consumer actually shipping `.github/actionlint.yaml`: ```yaml - id: actionlint args: - -config-file - .github/actionlint.yaml files: ^\.forgejo/workflows/.*\.(ya?ml)$ ``` Conditional rather than unconditional, and the issue's second option is not safe: actionlint exits 3 on a config path it cannot read, not silently. ``` $ actionlint -config-file .github/does-not-exist.yaml .forgejo/workflows/ci.yml could not read config file ".github/does-not-exist.yaml": open ...: no such file or directory exit=3 ``` An always-on flag would turn every consumer without a config red, trading one broken class for a larger one. Shape of the fix: * `ACTIONLINT_CONFIG_REL` plus `actionlint_args(repo_dir)` decide emission per consumer. * `managed_block()` and `empty_config_template()` take an optional `repo_dir`. `upsert_managed_block()` derives it from `config_path.parent`, so the create and refresh paths both carry it. * Two tests: one parsing the rendered block and asserting the args appear only with the config present, one driving a real apply plus refresh so the flag survives a block rewrite. Verified the rendered block passes `pre-commit validate-config`, and that actionlint accepts a Forgejo-only layout with the flag and rejects it without. On the current state note: `agent-compose` carries `args: [-config-file, .github/actionlint.yaml]` on the actionlint hook with no marker comment attached, so there is nothing to remove there. Its next apply will re-emit the same flag from the template.
Sign in to join this conversation.
No milestone
No project
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
coilyco-flight-deck/agentic-os#984
No description provided.