Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
23e27d9
Fix Strix dependency lock constraints
seonghobae Jun 30, 2026
a4b52c4
Allow Strix manual status fallback
seonghobae Jun 30, 2026
4b5628e
Merge branch 'main' into codex/fix-strix-dependency-lock
opencode-agent[bot] Jun 30, 2026
b520167
Merge branch 'main' into codex/fix-strix-dependency-lock
opencode-agent[bot] Jun 30, 2026
e12eafa
Merge branch 'main' into codex/fix-strix-dependency-lock
opencode-agent[bot] Jun 30, 2026
6ee58df
Merge branch 'main' into codex/fix-strix-dependency-lock
opencode-agent[bot] Jun 30, 2026
7b0e7bf
Recognize manual Strix success runs in OpenCode
seonghobae Jun 30, 2026
1f9411c
Merge branch 'main' into codex/fix-strix-dependency-lock
opencode-agent[bot] Jun 30, 2026
a0345e7
Merge remote-tracking branch 'origin/main' into codex/fix-strix-depen…
seonghobae Jun 30, 2026
355f0f7
Merge branch 'main' into codex/fix-strix-dependency-lock
opencode-agent[bot] Jun 30, 2026
9f05c6c
Fix OpenCode workflow heredoc parsing
seonghobae Jun 30, 2026
65e40c1
Trigger central required workflow evaluation
seonghobae Jun 30, 2026
1878454
Merge branch 'main' into codex/fix-strix-dependency-lock
opencode-agent[bot] Jun 30, 2026
8cb767e
Merge branch 'main' into codex/fix-strix-dependency-lock
opencode-agent[bot] Jun 30, 2026
e9877ad
Merge branch 'main' into codex/fix-strix-dependency-lock
opencode-agent[bot] Jun 30, 2026
60c5d2f
Limit OpenCode Docker evidence to changed Dockerfiles
seonghobae Jun 30, 2026
0a2fa62
Use advisory coverage reports in OpenCode evidence
seonghobae Jun 30, 2026
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: 31 additions & 15 deletions .github/workflows/opencode-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -349,27 +349,27 @@ jobs:
run_and_capture "Python configured CI test suite (${project_dir})" \
bash -c 'cd "$1" && PYTHONPATH=. bash -lc "$2"' bash "$project_dir" "$configured_command"
done <<<"$configured_commands"
elif [ -f "${project_dir}/pyproject.toml" ]; then
run_and_capture "Python coverage with missing-line report (${project_dir})" \
bash -c 'cd "$1" && PYTHONPATH=. uv run --with coverage --with pytest coverage run -m pytest tests && uv run --with coverage coverage report --show-missing --fail-under=100' bash "$project_dir"
else
run_and_capture "Python coverage with missing-line report (${project_dir})" \
bash -c 'cd "$1" && python3 -m pip install --disable-pip-version-check coverage pytest >/dev/null && PYTHONPATH=. python3 -m coverage run -m pytest tests && python3 -m coverage report --show-missing --fail-under=100' bash "$project_dir"
fi
elif [ -f "${project_dir}/pyproject.toml" ]; then
run_and_capture "Python coverage with missing-line report (${project_dir})" \
bash -c 'cd "$1" && PYTHONPATH=. uv run --with coverage --with pytest coverage run -m pytest tests && uv run --with coverage coverage report --show-missing' bash "$project_dir"
else
run_and_capture "Python coverage with missing-line report (${project_dir})" \
bash -c 'cd "$1" && python3 -m pip install --disable-pip-version-check coverage pytest >/dev/null && PYTHONPATH=. python3 -m coverage run -m pytest tests && python3 -m coverage report --show-missing' bash "$project_dir"
fi
done < <(tracked_python_projects_with_tests)

if [ "$measured_projects" -eq 0 ]; then
if has_tracked_files '*.py'; then
run_and_capture "Python coverage with missing-line report" \
bash -c 'python3 -m pip install --disable-pip-version-check coverage pytest >/dev/null && PYTHONPATH=. python3 -m coverage run -m pytest && python3 -m coverage report --show-missing --fail-under=100'
bash -c 'python3 -m pip install --disable-pip-version-check coverage pytest >/dev/null && PYTHONPATH=. python3 -m coverage run -m pytest && python3 -m coverage report --show-missing'
elif python3 -c 'import pytest_cov' >/dev/null 2>&1; then
run_and_capture "Python pytest-cov coverage" python3 -m pytest --cov=. --cov-report=term-missing
else
append "### Python test suite"
append ""
append "- Result: FAIL"
append "- Reason: Python source exists, but no tests directory or pytest collection contract was found."
append "- Fix: add repository tests discoverable by pytest, then rerun coverage with \`python3 -m coverage run -m pytest && python3 -m coverage report --show-missing --fail-under=100\`."
append "- Fix: add repository tests discoverable by pytest, then rerun coverage with \`python3 -m coverage run -m pytest && python3 -m coverage report --show-missing\`."
append ""
failures=$((failures + 1))
fi
Expand Down Expand Up @@ -650,14 +650,19 @@ jobs:
return
fi
run_and_capture "Docker runtime version" docker version
changed_dockerfiles="$(mktemp)"
while IFS= read -r dockerfile; do
if [ -f "$dockerfile" ]; then
printf '%s\n' "$dockerfile"
fi
done >"$changed_dockerfiles" < <(changed_files_for_coverage | grep -E '(^|/)Dockerfile(\..*)?$' || true)
while IFS= read -r dockerfile; do
[ -n "$dockerfile" ] || continue
context_dir="$(dirname "$dockerfile")"
tag_suffix="$(printf '%s' "$dockerfile" | tr '[:upper:]' '[:lower:]' | tr '/.' '--' | tr -cd '[:alnum:]-' | cut -c1-80)"
image_tag="opencode-review-${PR_HEAD_SHA:-head}-${tag_suffix}"
run_and_capture "Docker build (${dockerfile})" \
docker build --pull=false -f "$dockerfile" -t "$image_tag" "$context_dir"
done < <(git ls-files 'Dockerfile' '*/Dockerfile' 'Dockerfile.*' '*/Dockerfile.*')
docker build --pull=false -f "$dockerfile" -t "$image_tag" .
done <"$changed_dockerfiles"
if has_changed_tracked_files 'docker-compose.yml' 'docker-compose.yaml' 'compose.yml' 'compose.yaml'; then
for compose_file in docker-compose.yml docker-compose.yaml compose.yml compose.yaml; do
if [ -f "$compose_file" ]; then
Expand Down Expand Up @@ -4090,9 +4095,7 @@ jobs:
fi

manual_run_line="$(latest_current_head_manual_strix_run || true)"
IFS="$(printf '\t')" read -r manual_run_status manual_run_conclusion manual_run_url <<EOF
${manual_run_line}
EOF
IFS="$(printf '\t')" read -r manual_run_status manual_run_conclusion manual_run_url <<<"$manual_run_line" || true
if [ "$manual_run_status" = "completed" ] &&
[ "$manual_run_conclusion" = "success" ] &&
[ -n "$manual_run_url" ]; then
Expand Down Expand Up @@ -4184,12 +4187,25 @@ EOF
local output_file="$2"
local manual_strix_success_target
local manual_strix_success_run_id
local manual_strix_run_info
local manual_strix_status
local manual_strix_conclusion
local manual_strix_url
local failed_strix_run_id

manual_strix_success_target="$(current_head_manual_strix_success_status || true)"
if [ -z "$manual_strix_success_target" ]; then
manual_strix_success_target="$(current_head_successful_strix_check_run || true)"
fi
if [ -z "$manual_strix_success_target" ]; then
manual_strix_run_info="$(latest_current_head_manual_strix_run || true)"
IFS=$'\t' read -r manual_strix_status manual_strix_conclusion manual_strix_url <<<"$manual_strix_run_info" || true
if [ "$manual_strix_status" = "completed" ] &&
[ "$manual_strix_conclusion" = "success" ] &&
[ -n "$manual_strix_url" ]; then
manual_strix_success_target="$manual_strix_url"
fi
fi
if [ -n "$manual_strix_success_target" ]; then
manual_strix_success_run_id="$(printf '%s' "$manual_strix_success_target" | sed -n 's#.*/actions/runs/\([0-9][0-9]*\).*#\1#p')"
while IFS= read -r rollup_line; do
Expand Down
61 changes: 43 additions & 18 deletions .github/workflows/strix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ permissions:
contents: read
id-token: write
models: read
statuses: write

jobs:
strix:
Expand Down Expand Up @@ -603,7 +604,8 @@ jobs:
- name: Publish same-head manual Strix status
if: ${{ always() && !cancelled() && github.event_name == 'workflow_dispatch' && github.event.inputs.pr_head_sha != '' }}
env:
GH_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || github.token }}
PRIMARY_STATUS_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || '' }}
FALLBACK_STATUS_TOKEN: ${{ github.token }}
TARGET_REPOSITORY: ${{ github.event.inputs.target_repository || github.repository }}
PR_HEAD_SHA: ${{ github.event.inputs.pr_head_sha }}
STRIX_RESULT: ${{ job.status }}
Expand All @@ -629,14 +631,25 @@ jobs:
;;
esac

gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \
-f state="$state" \
-f context="strix" \
-f description="$description" \
-f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || {
echo "::warning::Could not publish manual Strix status from scan job; keeping scan evidence result authoritative in the workflow run."
exit 0
}
post_strix_status() {
token="$1"
if [ -z "$token" ]; then
return 1
fi
GH_TOKEN="$token" gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \
-f state="$state" \
-f context="strix" \
-f description="$description" \
-f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
}

if post_strix_status "$PRIMARY_STATUS_TOKEN"; then
exit 0
fi
if [ "$TARGET_REPOSITORY" = "$GITHUB_REPOSITORY" ] && post_strix_status "$FALLBACK_STATUS_TOKEN"; then
exit 0
fi
echo "::warning::Could not publish manual Strix status from scan job; keeping scan evidence result authoritative in the workflow run."

publish-manual-pr-evidence-status:
name: publish-manual-pr-evidence-status
Expand Down Expand Up @@ -715,7 +728,8 @@ jobs:

- name: Publish same-head manual Strix status
env:
GH_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || github.token }}
PRIMARY_STATUS_TOKEN: ${{ steps.target_app_token.outputs.token || secrets.OPENCODE_APPROVE_TOKEN || '' }}
FALLBACK_STATUS_TOKEN: ${{ github.token }}
TARGET_REPOSITORY: ${{ github.event.inputs.target_repository || github.repository }}
PR_HEAD_SHA: ${{ github.event.inputs.pr_head_sha }}
STRIX_RESULT: ${{ needs.strix.result }}
Expand All @@ -741,11 +755,22 @@ jobs:
;;
esac

gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \
-f state="$state" \
-f context="strix" \
-f description="$description" \
-f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" || {
echo "::warning::Could not publish manual Strix status from follow-up job; scan job publishes the authoritative status when target credentials are available."
exit 0
}
post_strix_status() {
token="$1"
if [ -z "$token" ]; then
return 1
fi
GH_TOKEN="$token" gh api -X POST "repos/${TARGET_REPOSITORY}/statuses/${PR_HEAD_SHA}" \
-f state="$state" \
-f context="strix" \
-f description="$description" \
-f target_url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
}

if post_strix_status "$PRIMARY_STATUS_TOKEN"; then
exit 0
fi
if [ "$TARGET_REPOSITORY" = "$GITHUB_REPOSITORY" ] && post_strix_status "$FALLBACK_STATUS_TOKEN"; then
exit 0
fi
echo "::warning::Could not publish manual Strix status from follow-up job; scan job publishes the authoritative status when target credentials are available."
4 changes: 2 additions & 2 deletions scripts/ci/test_strix_quick_gate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -650,8 +650,8 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() {
assert_file_contains "$workflow_file" "Repository docstring coverage" "opencode coverage evidence accepts repository-owned docstring coverage scripts"
assert_file_contains "$workflow_file" "check:python-docstrings" "opencode coverage evidence can use repository Python docstring gates exposed through package scripts"
assert_file_contains "$workflow_file" "Coverage execution evidence" "opencode evidence exposes coverage measurement to the review model"
assert_file_contains "$workflow_file" 'context_dir="$(dirname "$dockerfile")"' "opencode Docker evidence builds each Dockerfile from its containing directory"
assert_file_contains "$workflow_file" 'docker build --pull=false -f "$dockerfile" -t "$image_tag" "$context_dir"' "opencode Docker evidence keeps Dockerfile paths relative to the source checkout"
assert_file_contains "$workflow_file" 'changed_files_for_coverage | grep -E' "opencode Docker evidence limits Docker builds to changed Dockerfiles"
assert_file_contains "$workflow_file" 'docker build --pull=false -f "$dockerfile" -t "$image_tag" .' "opencode Docker evidence builds changed Dockerfiles from the repository root context"
assert_file_contains "$workflow_file" "has_changed_tracked_files 'docker-compose.yml' 'docker-compose.yaml' 'compose.yml' 'compose.yaml'" "opencode Docker evidence runs compose checks only when compose files changed"
assert_file_contains "$workflow_file" "Coverage and Docstring coverage labels must cite Coverage execution evidence showing supported repository test suites passed" "opencode approval requires passing test evidence when coverage is applicable"
assert_file_contains "$workflow_file" "or explicitly cite Coverage execution evidence as not applicable because no supported source files or package manifests were found" "opencode approval permits only evidence-backed no-source coverage N/A"
Expand Down
Loading