Files
llm-wiki/raw/errors/gitea-act-missing-jq-job-bootstrap-2026-06-23.md
T

6.1 KiB

title, source_type, status, related_branches, related_projects, tags, created, status_label
title source_type status related_branches related_projects tags created status_label
error / Gitea act job jq bootstrap 누락 error-note raw
feature-build-release-supply-chain-contract
ca-skeleton
error
ca-skeleton
ci-cd
build-tooling
supply-chain
2026-06-23 resolved

error: Gitea act job jq bootstrap 누락

Layer: raw/errors/ — Gitea/act minimal job image에서 jq가 없어서 공급망 계약 테스트가 차단된 원인과 보완 기록.

Parent / 부모

증상 / Symptom

  • 에러 메시지 (CI 로그 원문):
    /workspace/donghyun.kang/ca-tmpl/.github/scripts/create-release-manifest.sh: line 52: jq: command not found
    exitcode '127': command not found, please refer to https://github.com/nektos/act/issues/107 for more information
    
  • 발생 컨텍스트: ci-quality-gates/gate-matrix-lint에서 gate matrix와 D1-D13 정적 계약이 성공한 다음 test-supply-chain-scripts.sh가 release manifest를 생성할 때 발생.
  • 발생 시점: 2026-06-21 05:38 UTC.
  • 발생 환경: Gitea Actions k8s-runner-1 v0.2.11, job image node:20-bullseye.
  • 재현 가능 여부: always — jq가 없는 동일 job image에서 해당 스크립트를 실행하면 종료 코드 127.

재현 절차 / Reproduction

  1. Gitea/act runner에서 ubuntu-latest를 jq가 포함되지 않은 node:20-bullseye로 매핑한다.
  2. .github/workflows/ci-quality-gates.ymlgate-matrix-lint를 실행한다.
  3. 기대 결과는 공급망 behavior test 성공이지만, 실제 결과는 create-release-manifest.sh의 첫 jq 호출에서 종료 코드 127이다.
  4. upstream gate-matrix-lint 실패를 받은 release-gate는 release-blocking gate 실패로 정상 차단된다.

조사 단계 / Investigation log

  • 2026-06-23 — 두 CI 로그를 대조했다. gate matrix와 verify-supply-chain-contract.sh는 성공했고, behavior test만 jq 부재로 실패했다. release-gate는 이 upstream failure를 정상적으로 전파했다.
  • 2026-06-23 — workflow와 간접 호출을 전수 대조해 jq가 필요한 job environment 6개를 확인했다: gate-matrix-lint, contract, verify, promote, audit-retention, trivy-fs.
  • 2026-06-23 — 구현 전 정적 계약을 강화해 installer 부재, 6개 job 배선 누락, inline download 잔존을 합쳐 15개 위반으로 실패하는 RED를 확인했다.
  • 2026-06-23 — jq 1.8.1 AMD64 asset을 job-local 경로에 다운로드하고 고정 SHA-256을 검증한 뒤 실행했다. 설치된 jq로 공급망 manifest/retention 양·음수 테스트가 성공했다.
  • 2026-06-23 — 실패 로그와 동일한 third-party container에 private workspace를 mount하는 검증은 안전 정책으로 거부되어 중단했다. 우회하지 않고 실제 Gitea CI 재실행을 잔여 확인으로 남겼다.

근본 원인 / Root cause

  • 직접 원인: create-release-manifest.sh가 jq를 호출했지만 job의 PATH에 jq executable이 없었다.
  • 근본 원인: workflow가 jq를 명시적 job dependency로 bootstrap하지 않고 hosted runner의 ambient tool에 의존했다. Gitea/act의 minimal image는 이 암묵적 전제를 만족하지 않았다.
  • 트리거 조건: jq가 없는 job image에서 직접 jq를 호출하거나 create-release-manifest.sh/audit-rollback-retention.sh를 간접 호출한다.

Sources / 근거

해결 / Resolution

  • 적용한 조치:
    • .github/scripts/install-jq.sh에 jq 1.8.1, Linux AMD64/ARM64 asset, 공식 SHA-256을 고정했다.
    • RUNNER_ARCH에 따라 asset을 선택하고 RUNNER_TEMP 아래 설치한 뒤 GITHUB_PATH로 다음 step에 전달한다.
    • checksum mismatch, 다운로드 실패, 미지원 architecture는 fail-closed한다.
    • jq 소비 job 6개가 같은 installer를 호출하도록 연결하고 dependency workflow의 inline jq 다운로드를 제거했다.
    • verify-supply-chain-contract.sh가 installer 불변식, job-level 호출, inline download 금지를 검사한다.
  • 검증 방법:
    • RED: 정적 계약 15개 예상 위반.
    • GREEN: 공급망 정적 계약과 gate matrix lint 성공.
    • 공식 AMD64 asset checksum 검증 및 jq-1.8.1 실행 성공.
    • 설치된 jq로 test-supply-chain-scripts.sh 성공.
    • 네 workflow YAML parse 성공.
    • Gradle architecture, ArchUnit, full test, check verifyPublicPathSnapshot 성공.
  • 잔여 위험 / 후속 작업: 변경 commit으로 실제 Gitea/act gate-matrix-lint를 재실행해 설치와 behavior test 로그를 확인해야 한다. github.com egress가 없는 runner의 internal mirror 정책은 별도 운영 결정이다.

회고 / Lessons

  • 빨리 감지하는 신호: 정적 계약은 성공했는데 behavior test가 종료 코드 127 또는 command not found로 실패하면 runner tool bootstrap 누락부터 확인한다.
  • 예방 체크리스트 항목 후보: shell script가 사용하는 외부 CLI를 호출 graph 기준으로 추적하고, 각 독립 job에 설치 step이 있는지 정적 계약으로 검사한다.
  • wiki로 끌어올릴 가치가 있는 일반화된 교훈: runner ambient tool 대신 version/checksum이 고정된 job-local bootstrap을 사용하고, 설치 구현은 한 파일로 중앙화한다.