|
| 1 | +name: Run Kipp Automation |
| 2 | +description: Execute a Kipp Managed Services automation through the runtime installed by setup-kipp |
| 3 | + |
| 4 | +inputs: |
| 5 | + automation-id: |
| 6 | + description: 'ID of the automation or combined pipeline. Must start with a lowercase letter or digit and contain at most 64 lowercase letters, digits and hyphens.' |
| 7 | + required: true |
| 8 | + github-token: |
| 9 | + description: 'Token used for GitHub API calls, Git pushes and `gh` commands. Pass a GitHub App token when the automation writes to the repository. Default: the workflow token.' |
| 10 | + required: false |
| 11 | + default: ${{ github.token }} |
| 12 | + phase: |
| 13 | + description: 'Execution stage. Use `all` for one invocation, or invoke `work` followed by `publish` in the same job when the GitHub token must be refreshed. Default: `all`.' |
| 14 | + required: false |
| 15 | + default: all |
| 16 | + subject-path: |
| 17 | + description: 'Path to a separate checkout containing the repository revision the automation will inspect or modify, such as a pull-request head.' |
| 18 | + required: false |
| 19 | + default: '' |
| 20 | + scrub-oidc-env: |
| 21 | + description: 'Clear the GitHub OIDC request variables before the automation runs and for the remainder of the job. Enable only when no provider or later step needs OIDC. Default: `false`.' |
| 22 | + required: false |
| 23 | + default: 'false' |
| 24 | + |
| 25 | +runs: |
| 26 | + using: "composite" |
| 27 | + |
| 28 | + steps: |
| 29 | + - name: Resolve automation inputs |
| 30 | + shell: bash |
| 31 | + env: |
| 32 | + AUTOMATION_ID: ${{ inputs.automation-id }} |
| 33 | + PHASE: ${{ inputs.phase }} |
| 34 | + RUNTIME_PATH: ${{ env.KIPP_RUNTIME_PATH }} |
| 35 | + AI_PROVIDER: ${{ env.KIPP_AI_PROVIDER }} |
| 36 | + SUBJECT_PATH: ${{ inputs.subject-path }} |
| 37 | + SCRUB_OIDC_ENV: ${{ inputs.scrub-oidc-env }} |
| 38 | + run: | |
| 39 | + set -euo pipefail |
| 40 | +
|
| 41 | + fail() { |
| 42 | + echo "::error::$1" |
| 43 | + exit 1 |
| 44 | + } |
| 45 | +
|
| 46 | + case "$SCRUB_OIDC_ENV" in |
| 47 | + true | false) ;; |
| 48 | + *) fail "scrub-oidc-env must be 'true' or 'false', received '$SCRUB_OIDC_ENV'." ;; |
| 49 | + esac |
| 50 | +
|
| 51 | + # The ID becomes part of runtime-managed paths. Reject unsafe characters. |
| 52 | + [[ "$AUTOMATION_ID" =~ ^[a-z0-9][a-z0-9-]{0,63}$ ]] || fail "automation-id must be lower case letters, digits and hyphens, received '$AUTOMATION_ID'." |
| 53 | +
|
| 54 | + case "$PHASE" in |
| 55 | + all | work | publish) ;; |
| 56 | + *) fail "phase must be 'all', 'work' or 'publish', received '$PHASE'." ;; |
| 57 | + esac |
| 58 | +
|
| 59 | + [ -n "$RUNTIME_PATH" ] || fail "No Kipp runtime is configured. Run the setup-kipp action before this action." |
| 60 | + [ -f "$RUNTIME_PATH" ] || fail "No Kipp runtime entry point exists at '$RUNTIME_PATH'." |
| 61 | +
|
| 62 | + case "$AI_PROVIDER" in |
| 63 | + openai-compatible | azure-foundry) ;; |
| 64 | + *) fail "No supported Kipp AI provider is configured. Run the setup-kipp action before this action." ;; |
| 65 | + esac |
| 66 | +
|
| 67 | + [ -d "$GITHUB_WORKSPACE/.kipp/automation" ] || fail "No automation package exists at '.kipp/automation' in the checked out repository." |
| 68 | +
|
| 69 | + if [ -n "$SUBJECT_PATH" ]; then |
| 70 | + [ -e "$SUBJECT_PATH" ] || fail "subject-path '$SUBJECT_PATH' does not exist." |
| 71 | + fi |
| 72 | +
|
| 73 | + echo "Running automation '$AUTOMATION_ID' in phase '$PHASE'." |
| 74 | +
|
| 75 | + # GITHUB_ENV applies the empty values to the automation and every later |
| 76 | + # step in the job. This is opt-in because some providers and downstream |
| 77 | + # steps legitimately exchange the job's OIDC identity. |
| 78 | + - name: Scrub OIDC request variables |
| 79 | + if: inputs.scrub-oidc-env == 'true' |
| 80 | + shell: bash |
| 81 | + run: | |
| 82 | + set -euo pipefail |
| 83 | + { |
| 84 | + echo "ACTIONS_ID_TOKEN_REQUEST_URL=" |
| 85 | + echo "ACTIONS_ID_TOKEN_REQUEST_TOKEN=" |
| 86 | + } >> "$GITHUB_ENV" |
| 87 | +
|
| 88 | + - name: Confirm OIDC request variables are scrubbed |
| 89 | + if: inputs.scrub-oidc-env == 'true' |
| 90 | + shell: bash |
| 91 | + run: | |
| 92 | + set -euo pipefail |
| 93 | + if [ -n "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ] || [ -n "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ]; then |
| 94 | + echo "::error::The OIDC request variables are still set for the automation step. Refusing to run." |
| 95 | + exit 1 |
| 96 | + fi |
| 97 | + echo "OIDC request variables are not visible to the automation step." |
| 98 | +
|
| 99 | + # Use github-script v9 or later because it runs on Node 24. The runtime |
| 100 | + # imports TypeScript automation modules and relies on Node 24's type stripping. |
| 101 | + # |
| 102 | + # Pass workflow values through the environment rather than interpolating |
| 103 | + # them into JavaScript, where untrusted values could become code. |
| 104 | + - name: Run automation |
| 105 | + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 |
| 106 | + env: |
| 107 | + KIPP_AUTOMATION_ID: ${{ inputs.automation-id }} |
| 108 | + KIPP_PHASE: ${{ inputs.phase }} |
| 109 | + KIPP_SUBJECT_PATH: ${{ inputs.subject-path }} |
| 110 | + # github-token configures github-script's Octokit client but does not |
| 111 | + # expose the token value. The runtime also needs the value for HTTPS Git |
| 112 | + # pushes and authenticated `gh` commands in the Pi subprocess. |
| 113 | + KIPP_GITHUB_TOKEN: ${{ inputs.github-token }} |
| 114 | + with: |
| 115 | + github-token: ${{ inputs.github-token }} |
| 116 | + script: | |
| 117 | + const { pathToFileURL } = await import("node:url") |
| 118 | + const runtime = await import(pathToFileURL(process.env.KIPP_RUNTIME_PATH).href) |
| 119 | + await runtime.runAutomation({ github, context, core, exec }) |
0 commit comments