Skip to main content

When the task needs its own workflow

Kadu's default execution runs the skill on a runner with Node, jq and Python. A task that depends on a tool the runner does not bring, on a known egress IP or on its own runner needs a GitHub Actions workflow in the repository itself.

Kobana's case is the security workspace: security-scan.yml installs the pentest suite, schedules the weekly and monthly scan and runs on a runner with a fixed egress IP. The template to copy is the same repository's wh-run-skill.yml: Playbook checkout, Claude Code installation, a stub of the helpers in /tmp/agent_state.sh, claude -p "/<plugin>:<skill>" --plugin-dir and set +e around the pipeline.

Two execution paths​

The task now has two paths, and what differs between them appears nowhere unless it is written down:

Run by KaduOwn workflow
RunnerKadu's, without the toolsthe workflow's, with the tools installed
Variablesonly what is in required_secretsonly what the step's env: block maps from secrets.*/vars.*
Instrumentationthe real consolethe stub, which only echoes in the run log
Output files$OUTPUT_FILES_DIR, published by Kaduthe workflow's own upload-artifact

Two consequences:

  • Every configuration variable goes in both places: in required_secrets, for Kadu, and in the workflow's env:, for the schedule. Forgetting one side makes the configuration apply on one path and fall back to the default on the other.
  • A missing tool becomes a pending item, not an error. A run from the console arrives without the tools: the skill records what was missing and moves on. Whoever needs the full execution is the workflow.

A workflow that generates traffic is born closed​

A workflow that generates traffic against third parties or against production is born fail-closed: without the authorization variable (vars.SECURITY_SCAN_AUTORIZADO=true, in Kobana's case), the job ends green with a ::notice and does nothing. A cron that is red every week because of missing configuration becomes noise nobody reads.