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

88 lines
6.1 KiB
Markdown

---
title: error / Gitea act job jq bootstrap 누락
source_type: error-note
status: raw
related_branches: [feature-build-release-supply-chain-contract]
related_projects: [ca-skeleton]
tags: [error, ca-skeleton, ci-cd, build-tooling, supply-chain]
created: 2026-06-23
status_label: resolved
---
# error: Gitea act job jq bootstrap 누락
> Layer: `raw/errors/` — Gitea/act minimal job image에서 jq가 없어서 공급망 계약 테스트가 차단된 원인과 보완 기록.
## Parent / 부모
- [[raw/branch-notes/feature-build-release-supply-chain-contract]]
## 증상 / Symptom
- 에러 메시지 (CI 로그 원문):
```text
/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.yml`의 `gate-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 / 근거
- [jq 1.8.1 release](https://github.com/jqlang/jq/releases/tag/jq-1.8.1) — Linux AMD64/ARM64 release assets와 checksum 고정 기준.
- [jq 1.8.1 release API](https://api.github.com/repos/jqlang/jq/releases/tags/jq-1.8.1) — asset digest metadata 확인.
- [[raw/errors/gitea-act-action-tag-and-dependency-graph-2026-06-20]] — 같은 runner에서 composite action의 CLI 설치 누락을 직접 CLI 설치로 전환한 선행 사례.
## 해결 / 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을 사용하고, 설치 구현은 한 파일로 중앙화한다.
## Related / 관련
- Parent: [[raw/branch-notes/feature-build-release-supply-chain-contract]].
- 선행 유사 오류: [[raw/errors/gitea-act-action-tag-and-dependency-graph-2026-06-20]].
- 별도 interview prep: 이번 보완에서는 신규 추출 없음. 기존 [[raw/interviews/digest-first-supply-chain-release-gates]]로 충분하다.
- 별도 blog topic: 이번 보완에서는 신규 추출 없음. 기존 [[raw/blog-topics/digest-first-java-release-pipeline-2026-06-21]]에 포함 가능한 하위 사례다.