发布

  • [OPIK-3662] [INFRA] feat: add actionlint workflow validation (#6600)

    frostbyte_neo 发布于 2026-05-18 11:11:59 +00:00

    • [OPIK-3662] [INFRA] feat: add actionlint workflow validation

    Adds actionlint as a CI gate for changed GitHub Actions workflow files,
    plus a matching pre-commit hook with graceful degradation when the
    binary is not installed locally. Both run with SHELLCHECK_OPTS=--severity=warning
    so the pre-existing SC2086 backlog (tracked in OPIK-6323) does not gate
    PRs while real warning+ findings still do.

    Real defects fixed alongside the enabling change:

    • 9 outdated action versions (publish_cursor_extension.yml@v2,
      setup-python@v3/v4 in 4 files, setup-node@v3 in 3 files, cache@v3,
      release-drafter@v5)
    • Script-injection risk in trigger_test_env_on_label.yaml: pull_request.head.ref
      is now passed via env: instead of interpolated into actions/github-script
      body
    • Deprecated set-output -> $GITHUB_OUTPUT (documentation_cookbook_tests.yml)
    • SC2046 unquoted command substitution in same file
    • workflow_call default value on a required input (build_and_publish_sdk.yaml)
    • Undeclared workflow_dispatch input ALLURE_JOB_RUN_ID (test_docs_links.yml)

    Deferred to OPIK-6323: 168 SC2086 quoting cleanup, 9 remaining cosmetic
    events default removals, 2 remaining expression issues, and tightening
    the gate to scan all files at default shellcheck severity.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • fix(ci): use unicode octopus in workflow name

    :octocat: is a GitHub markdown shortcode and only renders in places
    that go through GFM (PR descriptions, comments). It does not render in
    the Actions UI workflow name, where the raw string :octocat: Lint Workflows was showing instead. Switching to the unicode octopus 🐙
    which the Actions UI renders correctly.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • fix(ci): pin actionlint install via gh release + attestation verify

    Addresses Baz comment on PR #6600: the previous bash <(curl ...) install
    pulled the download script from a mutable URL with no integrity check.

    Replaces it with the upstream-recommended secure install path from
    https://github.com/rhysd/actionlint/blob/main/docs/install.md:

    1. Resolve the latest release tag via gh release view
    2. Download the linux_amd64 tarball as an immutable release asset
    3. Verify its GitHub artifact attestation (Sigstore-signed by rhysd's
      release CI) before executing — verifies provenance, not just bytes
    4. Echo the version in the workflow log for traceability

    This is strictly stronger than the SHA256-pinning Baz suggested:
    attestation verification confirms the artifact was built by the
    official rhysd/actionlint release workflow, not just that the bytes
    match a hardcoded hash. gh is preinstalled on GitHub-hosted runners,
    so no extra setup needed.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • feat(ci): also lint workflows that use changed composite actions

    Composite actions in .github/actions/*/action.yml can't be linted by
    actionlint directly (it treats them as workflows and complains about
    missing on:/jobs:). They're validated transitively when a workflow
    that references them is linted.

    Extends the gate (CI + pre-commit) to detect when a composite action
    is changed without a workflow edit, find the workflows that reference
    it via uses: ./.github/actions/<name>, and add those to the lint
    set. Avoids the full-tree fallback that would have tripped on the
    pre-existing baseline findings deferred to OPIK-6323.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com

    • refactor(ci): drop unnecessary const layer in trigger_test_env_on_label

    Addresses liyaka's review comment on PR #6600: the intermediate const headRef = process.env.HEAD_REF and const baseVersion = ... lines
    added ceremony for values used once. Inlines ${process.env.HEAD_REF}
    and ${process.env.BASE_VERSION} directly in the template literal.

    The env: block is preserved — that's the actual security primitive.
    Passing ${{ github.event.pull_request.head.ref }} via env: (rather
    than inlining it into the script body) prevents script injection,
    because env: values are read at runtime via process.env rather than
    substituted into the script source by ${{ }} expansion. Added a
    comment block above the env: keys explaining this so the indirection
    is no longer mysterious.

    Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com


    Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com

    下载附件