Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 41 additions & 5 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,7 @@ jobs:
GH_TOKEN: ${{ steps.opencode_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || github.token }}
OPENCODE_APP_TOKEN: ${{ steps.opencode_app_token.outputs.token }}
OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
GH_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.event.inputs.pr_head_sha }}
Expand Down Expand Up @@ -1035,6 +1036,7 @@ jobs:
STRIX_GITHUB_MODELS_TOKEN: ${{ secrets.STRIX_GITHUB_MODELS_TOKEN }}
OPENCODE_APP_TOKEN: ${{ steps.opencode_app_token.outputs.token }}
OPENCODE_APPROVE_TOKEN: ${{ secrets.OPENCODE_APPROVE_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
OPENCODE_EVIDENCE_FILE: ${{ runner.temp }}/opencode-review-evidence.md
OPENCODE_FAILED_CHECK_EVIDENCE_FILE: ${{ runner.temp }}/opencode-failed-check-evidence.md
OPENCODE_FAILED_CHECK_DIAGNOSIS_FILE: ${{ runner.temp }}/opencode-failed-check-diagnosis.md
Expand Down Expand Up @@ -1089,19 +1091,39 @@ jobs:
printf '%s\n' "$body"
} >"$overview_body_file"

local tmp_err
tmp_err="$(mktemp)"

overview_comment_id="$(
env GH_TOKEN="$overview_comment_token" \
gh api -X GET "repos/${GH_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate \
--jq '[.[] | select((.user.login == "github-actions[bot]" or .user.login == "opencode-agent[bot]") and (.body | contains("<!-- opencode-review-overview -->")))] | sort_by(.created_at) | last.id // empty'
)"
--jq '[.[] | select((.user.login == "github-actions[bot]" or .user.login == "opencode-agent[bot]") and (.body | contains("<!-- opencode-review-overview -->")))] | sort_by(.created_at) | last.id // empty' 2>"$tmp_err"
)" || {
if grep -q "HTTP 401" "$tmp_err"; then
if [ -n "${OPENCODE_APPROVE_TOKEN:-}" ]; then
overview_comment_token="$OPENCODE_APPROVE_TOKEN"
elif [ -n "${GITHUB_TOKEN:-}" ]; then
overview_comment_token="$GITHUB_TOKEN"
fi
overview_comment_id="$(
env GH_TOKEN="$overview_comment_token" \
gh api -X GET "repos/${GH_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate \
--jq '[.[] | select((.user.login == "github-actions[bot]" or .user.login == "opencode-agent[bot]") and (.body | contains("<!-- opencode-review-overview -->")))] | sort_by(.created_at) | last.id // empty'
)"
else
cat "$tmp_err" >&2
fi
}
rm -f "$tmp_err"

if [ -n "$overview_comment_id" ]; then
jq -n --rawfile body "$overview_body_file" '{body: $body}' |
env GH_TOKEN="$overview_comment_token" \
gh api -X PATCH "repos/${GH_REPOSITORY}/issues/comments/${overview_comment_id}" --input - >/dev/null
gh api -X PATCH "repos/${GH_REPOSITORY}/issues/comments/${overview_comment_id}" --input - >/dev/null || true
else
jq -n --rawfile body "$overview_body_file" '{body: $body}' |
env GH_TOKEN="$overview_comment_token" \
gh api -X POST "repos/${GH_REPOSITORY}/issues/${PR_NUMBER}/comments" --input - >/dev/null
gh api -X POST "repos/${GH_REPOSITORY}/issues/${PR_NUMBER}/comments" --input - >/dev/null || true
fi
rm -f "$overview_body_file"
}
Expand Down Expand Up @@ -2072,11 +2094,24 @@ jobs:
local attempts="${CHECK_LOOKUP_RETRY_ATTEMPTS:-5}"
local sleep_seconds="${CHECK_LOOKUP_RETRY_SLEEP_SECONDS:-5}"
local attempt=1
local stderr_file
stderr_file="$(mktemp)"

while [ "$attempt" -le "$attempts" ]; do
if "$collector" "$output_file"; then
if "$collector" "$output_file" 2>"$stderr_file"; then
rm -f "$stderr_file"
return 0
fi
cat "$stderr_file" >&2
if grep -q "HTTP 401" "$stderr_file"; then
if [ -n "${OPENCODE_APPROVE_TOKEN:-}" ]; then
export GH_TOKEN="$OPENCODE_APPROVE_TOKEN"
overview_comment_token="$OPENCODE_APPROVE_TOKEN"
elif [ -n "${GITHUB_TOKEN:-}" ]; then
export GH_TOKEN="$GITHUB_TOKEN"
overview_comment_token="$GITHUB_TOKEN"
fi
fi
Comment on lines +2106 to +2114
: >"$output_file"
if [ "$attempt" -lt "$attempts" ]; then
printf 'GitHub Checks lookup failed; retrying %s/%s before changing review state.\n' "$attempt" "$attempts" >&2
Expand All @@ -2085,6 +2120,7 @@ jobs:
attempt=$((attempt + 1))
done

rm -f "$stderr_file"
return 1
}

Expand Down
61 changes: 11 additions & 50 deletions scripts/checks/verify_supply_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1216,30 +1216,23 @@ def is_blocking_required_step(block_lines: list[str], block_indent: int) -> bool
return []


def _verify_ci_coverage(missing: list[str]) -> None:
def verify_workflow_coverage() -> list[str]:
"""Return workflow trigger and artifact coverage violations."""
missing: list[str] = []
ci = read_workflow(Path(".github/workflows/ci.yml"), "ci", missing)
for token in ["develop", "main", "pull_request", "push", "ci / build-and-test"]:
if ci and token not in ci:
missing.append(f"ci workflow missing token: {token}")


def _verify_sbom_coverage(missing: list[str]) -> None:
sbom = read_workflow(Path(".github/workflows/sbom.yml"), "sbom", missing)
for token in ["develop", "main", "pull_request", "release:", "tags:"]:
if sbom and token not in sbom:
missing.append(f"sbom workflow missing trigger token: {token}")


def _verify_dependency_review_coverage(missing: list[str]) -> None:
review = read_workflow(
Path(".github/workflows/dependency-review.yml"), "dependency review", missing
)
for token in ["develop", "main", "pull_request"]:
if review and token not in review:
missing.append(f"dependency review workflow missing trigger token: {token}")


def _verify_security_audit_coverage(missing: list[str]) -> None:
audit = read_workflow(
Path(".github/workflows/security-audit.yml"), "security audit", missing
)
Expand All @@ -1266,16 +1259,10 @@ def _verify_security_audit_coverage(missing: list[str]) -> None:
missing.append(
f"security audit workflow missing vulnerability audit token: {token}"
)


def _verify_codeql_coverage(missing: list[str]) -> None:
codeql = read_workflow(Path(".github/workflows/codeql.yml"), "codeql", missing)
for token in ["develop", "main", "pull_request", "push", "codeql"]:
if codeql and token not in codeql:
missing.append(f"codeql workflow missing token: {token}")


def _verify_release_coverage(missing: list[str]) -> None:
release = read_workflow(Path(".github/workflows/release.yml"), "release", missing)
for token in [
"develop",
Expand All @@ -1287,18 +1274,12 @@ def _verify_release_coverage(missing: list[str]) -> None:
]:
if release and token not in release:
missing.append(f"release workflow missing token: {token}")


def _verify_secret_scan_coverage(missing: list[str]) -> None:
secret_scan = read_workflow(
Path(".github/workflows/secret-scan-gate.yml"), "secret scan", missing
)
for token in ["develop", "main", "pull_request", "push", "secret-scan-gate"]:
if secret_scan and token not in secret_scan:
missing.append(f"secret scan workflow missing token: {token}")


def _verify_build_coverage(missing: list[str]) -> None:
build = read_workflow(
Path(".github/workflows/build-baseline.yml"), "build baseline", missing
)
Expand Down Expand Up @@ -1336,9 +1317,14 @@ def _verify_build_coverage(missing: list[str]) -> None:
missing.append(
"build workflow should not rely on macos-latest for architecture coverage"
)


def _verify_scorecard_coverage(missing: list[str], workflow_paths: list[Path]) -> None:
workflow_paths = sorted(Path(".github/workflows").glob("*.yml")) + sorted(
Path(".github/workflows").glob("*.yaml")
)
for workflow_path in workflow_paths:
workflow_content = workflow_path.read_text(encoding="utf-8")
missing.extend(
release_artifact_download_decompression_violations(workflow_content)
)
scorecard = read_workflow(
Path(".github/workflows/ossf-scorecard.yml"), "ossf scorecard", missing
)
Expand Down Expand Up @@ -1381,31 +1367,6 @@ def _verify_scorecard_coverage(missing: list[str], workflow_paths: list[Path]) -
workflow_content, workflow_path
)
)


def verify_workflow_coverage() -> list[str]:
"""Return workflow trigger and artifact coverage violations."""
missing: list[str] = []
_verify_ci_coverage(missing)
_verify_sbom_coverage(missing)
_verify_dependency_review_coverage(missing)
_verify_security_audit_coverage(missing)
_verify_codeql_coverage(missing)
_verify_release_coverage(missing)
_verify_secret_scan_coverage(missing)
_verify_build_coverage(missing)

workflow_paths = sorted(Path(".github/workflows").glob("*.yml")) + sorted(
Path(".github/workflows").glob("*.yaml")
)
for workflow_path in workflow_paths:
workflow_content = workflow_path.read_text(encoding="utf-8")
missing.extend(
release_artifact_download_decompression_violations(workflow_content)
)

_verify_scorecard_coverage(missing, workflow_paths)

return missing


Expand Down
Loading