Skip to content
Open
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
184 changes: 182 additions & 2 deletions .github/workflows/noema-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ run-name: >-

on:
pull_request_target:
types: [opened, synchronize, reopened, ready_for_review, closed]
types: [opened, synchronize, reopened, ready_for_review, edited, closed]
workflow_run:
workflows: ["Required OpenCode Review", "Strix Security Scan"]
types: [completed]
Expand Down Expand Up @@ -66,6 +66,96 @@ jobs:
run: |
echo "::notice::Noema review skipped: no pull request number is associated with this event."

- name: Bind Noema inputs to the live organization pull request
if: env.PR_NUMBER != ''
id: live_pr
env:
GH_TOKEN: ${{ github.token }}
EVENT_NAME: ${{ github.event_name }}
DISPATCH_ACTOR: ${{ github.triggering_actor }}
DISPATCH_SENDER: ${{ github.event.sender.login || '' }}
ALLOWED_DISPATCH_ACTOR: ${{ vars.NOEMA_REPOSITORY_DISPATCH_ACTOR || '' }}
ALLOWED_DISPATCH_TARGETS: ${{ vars.NOEMA_REPOSITORY_DISPATCH_TARGETS || '' }}
SUPPLIED_BASE_REF: ${{ github.event.client_payload.pr_base_ref || '' }}
SUPPLIED_BASE_SHA: ${{ github.event.client_payload.pr_base_sha || '' }}
SUPPLIED_HEAD_REF: ${{ github.event.client_payload.pr_head_ref || '' }}
SUPPLIED_HEAD_SHA: ${{ github.event.client_payload.pr_head_sha || '' }}
run: |
set -euo pipefail

fail_validation() {
echo "::error::$1"
exit 1
}

if [[ ! "$TARGET_REPOSITORY" =~ ^ContextualWisdomLab/[A-Za-z0-9_.-]+$ ]]; then
fail_validation "Noema target repository must be an exact ContextualWisdomLab repository name."
fi
if [[ ! "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]]; then
fail_validation "Noema pull request number must be a positive integer."
fi

if [ "$EVENT_NAME" = "repository_dispatch" ]; then
if [ -z "$ALLOWED_DISPATCH_ACTOR" ]; then
fail_validation "NOEMA_REPOSITORY_DISPATCH_ACTOR must be configured before repository_dispatch can mint reviewer credentials."
fi
if [ "$DISPATCH_ACTOR" != "$ALLOWED_DISPATCH_ACTOR" ] || [ "$DISPATCH_SENDER" != "$ALLOWED_DISPATCH_ACTOR" ]; then
fail_validation "Noema repository_dispatch actor and sender must exactly match the configured identity."
fi
target_allowed=false
IFS=',' read -ra allowed_targets <<<"$ALLOWED_DISPATCH_TARGETS"
for allowed_target in "${allowed_targets[@]}"; do
if [ "$TARGET_REPOSITORY" = "${allowed_target//[[:space:]]/}" ]; then
target_allowed=true
break
fi
done
if [ "$target_allowed" != true ]; then
fail_validation "Noema repository_dispatch target is not present in NOEMA_REPOSITORY_DISPATCH_TARGETS."
fi
fi

if ! live_pr="$(gh api "repos/${TARGET_REPOSITORY}/pulls/${PR_NUMBER}")"; then
fail_validation "Noema could not load the requested live pull request."
fi
state="$(jq -r '.state // empty' <<<"$live_pr")"
base_repository="$(jq -r '.base.repo.full_name // empty' <<<"$live_pr")"
head_repository="$(jq -r '.head.repo.full_name // empty' <<<"$live_pr")"
base_ref="$(jq -r '.base.ref // empty' <<<"$live_pr")"
base_sha="$(jq -r '.base.sha // empty' <<<"$live_pr")"
head_ref="$(jq -r '.head.ref // empty' <<<"$live_pr")"
head_sha="$(jq -r '.head.sha // empty' <<<"$live_pr")"

if [ "$state" != "open" ]; then
fail_validation "Noema only reviews open pull requests."
fi
if [ "$base_repository" != "$TARGET_REPOSITORY" ] || [ "$head_repository" != "$TARGET_REPOSITORY" ]; then
fail_validation "Noema reviewer credentials are restricted to same-repository pull requests."
fi
if [[ ! "$base_ref" =~ ^[A-Za-z0-9._/-]+$ ]] || [[ ! "$head_ref" =~ ^[A-Za-z0-9._/-]+$ ]]; then
fail_validation "Noema live pull request refs are invalid."
fi
if [[ ! "$base_sha" =~ ^[0-9a-fA-F]{40}$ ]] || [[ ! "$head_sha" =~ ^[0-9a-fA-F]{40}$ ]]; then
fail_validation "Noema live pull request SHAs are invalid."
fi

if [ "$EVENT_NAME" = "repository_dispatch" ]; then
if [ "$SUPPLIED_BASE_REF" != "$base_ref" ] || [ "$SUPPLIED_BASE_SHA" != "$base_sha" ] || \
[ "$SUPPLIED_HEAD_REF" != "$head_ref" ] || [ "$SUPPLIED_HEAD_SHA" != "$head_sha" ]; then
fail_validation "Noema repository_dispatch payload does not match the live base/head identity."
fi
fi

{
echo "target_repository=$TARGET_REPOSITORY"
echo "repository_name=${TARGET_REPOSITORY#*/}"
echo "pr_number=$PR_NUMBER"
echo "base_ref=$base_ref"
echo "base_sha=$base_sha"
echo "head_ref=$head_ref"
echo "head_sha=$head_sha"
} >>"$GITHUB_OUTPUT"

- name: Resolve trusted Noema review source ref
if: env.PR_NUMBER != ''
id: trusted_source
Expand Down Expand Up @@ -139,6 +229,7 @@ jobs:
if: env.PR_NUMBER != ''
id: noema_credential
env:
TARGET_REPOSITORY: ${{ steps.live_pr.outputs.target_repository }}
NOEMA_GITHUB_APP_CLIENT_ID: ${{ vars.NOEMA_GITHUB_APP_CLIENT_ID || '' }}
NOEMA_GITHUB_APP_PRIVATE_KEY: ${{ secrets.NOEMA_GITHUB_APP_PRIVATE_KEY || '' }}
TOKEN_EXCHANGE_URL: ${{ vars.NOEMA_TOKEN_EXCHANGE_URL || vars.NOEMA_EXCHANGE_URL || '' }}
Expand Down Expand Up @@ -182,7 +273,7 @@ jobs:
client-id: ${{ vars.NOEMA_GITHUB_APP_CLIENT_ID }}
private-key: ${{ secrets.NOEMA_GITHUB_APP_PRIVATE_KEY }}
owner: ContextualWisdomLab
repositories: ${{ steps.noema_credential.outputs.repository }}
repositories: ${{ steps.live_pr.outputs.repository_name }}
permission-actions: read
permission-checks: read
permission-contents: read
Expand All @@ -196,6 +287,7 @@ jobs:
if: env.PR_NUMBER != '' && steps.noema_credential.outputs.source == 'oidc'
id: noema_oidc_token
env:
TARGET_REPOSITORY: ${{ steps.live_pr.outputs.target_repository }}
OIDC_AUDIENCE: ${{ vars.NOEMA_OIDC_AUDIENCE || 'cwl-noema-review' }}
TOKEN_EXCHANGE_URL: ${{ vars.NOEMA_TOKEN_EXCHANGE_URL || vars.NOEMA_EXCHANGE_URL || '' }}
run: |
Expand Down Expand Up @@ -250,14 +342,102 @@ jobs:
echo "::add-mask::$app_token"
echo "token=$app_token" >>"$GITHUB_OUTPUT"

- name: Materialize exact OpenCode approval evidence
if: env.PR_NUMBER != ''
id: primary_approval_evidence
env:
GH_TOKEN: ${{ secrets.NOEMA_REVIEW_TOKEN || steps.noema_github_app_token.outputs.token || steps.noema_oidc_token.outputs.token }}
GH_REPOSITORY: ${{ steps.live_pr.outputs.target_repository }}
PR_BASE_REF: ${{ steps.live_pr.outputs.base_ref }}
PR_BASE_SHA: ${{ steps.live_pr.outputs.base_sha }}
PR_HEAD_REF: ${{ steps.live_pr.outputs.head_ref }}
PR_HEAD_SHA: ${{ steps.live_pr.outputs.head_sha }}
OPENCODE_SOURCE_GIT_DIR: ${{ runner.temp }}/noema-pr-objects.git
OPENCODE_SOURCE_WORKDIR: ${{ runner.temp }}/noema-pr-head
OPENCODE_SOURCE_MANIFEST: ${{ runner.temp }}/noema-pr-source-manifest.json
OPENCODE_CHANGED_FILES_FILE: ${{ runner.temp }}/opencode-changed-files.txt
OPENCODE_ARTIFACT_MANIFEST_FILE: ${{ runner.temp }}/opencode-artifact-manifest.json
run: |
set -euo pipefail
if [ -z "${GH_TOKEN:-}" ]; then
echo "::error::Noema reviewer token is unavailable for exact approval evidence."
exit 1
fi
git check-ref-format "refs/heads/$PR_BASE_REF"
git check-ref-format "refs/heads/$PR_HEAD_REF"
gh auth setup-git
rm -rf "$OPENCODE_SOURCE_GIT_DIR" "$OPENCODE_SOURCE_WORKDIR"
rm -f "$OPENCODE_SOURCE_MANIFEST" "$OPENCODE_CHANGED_FILES_FILE" \
"$OPENCODE_ARTIFACT_MANIFEST_FILE"
git init --bare "$OPENCODE_SOURCE_GIT_DIR"
git --git-dir="$OPENCODE_SOURCE_GIT_DIR" remote add pr-source \
"$GITHUB_SERVER_URL/$GH_REPOSITORY.git"
git --git-dir="$OPENCODE_SOURCE_GIT_DIR" fetch --no-tags --no-recurse-submodules \
pr-source "+refs/heads/${PR_BASE_REF}:refs/remotes/pr-source/base"
git --git-dir="$OPENCODE_SOURCE_GIT_DIR" fetch --no-tags --no-recurse-submodules \
pr-source "+refs/heads/${PR_HEAD_REF}:refs/remotes/pr-source/head"
[ "$(git --git-dir="$OPENCODE_SOURCE_GIT_DIR" rev-parse refs/remotes/pr-source/base)" = "$PR_BASE_SHA" ]
[ "$(git --git-dir="$OPENCODE_SOURCE_GIT_DIR" rev-parse refs/remotes/pr-source/head)" = "$PR_HEAD_SHA" ]
git --git-dir="$OPENCODE_SOURCE_GIT_DIR" update-ref refs/heads/noema-review "$PR_HEAD_SHA"
git --git-dir="$OPENCODE_SOURCE_GIT_DIR" symbolic-ref HEAD refs/heads/noema-review
python3 scripts/ci/materialize_pr_review_source.py \
--git-dir "$OPENCODE_SOURCE_GIT_DIR" \
--head-sha "$PR_HEAD_SHA" \
--output-dir "$OPENCODE_SOURCE_WORKDIR" \
--manifest "$OPENCODE_SOURCE_MANIFEST"
merge_base="$(git -C "$OPENCODE_SOURCE_WORKDIR" merge-base "$PR_BASE_SHA" "$PR_HEAD_SHA")"
git -C "$OPENCODE_SOURCE_WORKDIR" diff --name-only --find-renames \
"$merge_base" "$PR_HEAD_SHA" >"$OPENCODE_CHANGED_FILES_FILE"
if [ ! -s "$OPENCODE_CHANGED_FILES_FILE" ]; then
echo "::error::Noema cannot validate an approval without a non-empty exact-head changed-file manifest."
exit 1
fi
python3 <<'PY'
import hashlib
import json
import os
from pathlib import Path

runner_temp = Path(os.environ["RUNNER_TEMP"]).resolve(strict=True)
changed_files = Path(os.environ["OPENCODE_CHANGED_FILES_FILE"]).resolve(strict=True)
if changed_files != runner_temp / "opencode-changed-files.txt":
raise SystemExit("changed-file evidence escaped runner temp")
changed_files.chmod(0o600)
manifest = Path(os.environ["OPENCODE_ARTIFACT_MANIFEST_FILE"])
manifest.write_text(
json.dumps(
{
"schema": 1,
"artifacts": {
changed_files.name: hashlib.sha256(
changed_files.read_bytes()
).hexdigest()
},
},
sort_keys=True,
),
encoding="utf-8",
)
manifest.chmod(0o600)
digest = hashlib.sha256(manifest.read_bytes()).hexdigest()
with Path(os.environ["GITHUB_OUTPUT"]).open("a", encoding="utf-8") as output:
output.write(f"manifest_sha256={digest}\n")
PY

- name: Run Noema LLM review and submit verdict
if: env.PR_NUMBER != ''
env:
TARGET_REPOSITORY: ${{ steps.live_pr.outputs.target_repository }}
PR_NUMBER: ${{ steps.live_pr.outputs.pr_number }}
GH_TOKEN: ${{ secrets.NOEMA_REVIEW_TOKEN || steps.noema_github_app_token.outputs.token || steps.noema_oidc_token.outputs.token }}
NOEMA_REVIEW_TOKEN_SOURCE: ${{ steps.noema_credential.outputs.source == 'pat' && 'noema-review-pat' || steps.noema_credential.outputs.source == 'github-app' && 'noema-review-github-app' || 'noema-review-app-oidc' }}
NOEMA_LLM_API_URL: ${{ vars.NOEMA_LLM_API_URL || '' }}
NOEMA_LLM_MODEL: ${{ vars.NOEMA_LLM_MODEL || '' }}
NOEMA_LLM_API_KEY: ${{ secrets.NOEMA_LLM_API_KEY || secrets.OPENAI_API_KEY || '' }}
OPENCODE_REQUIRE_ADVERSARIAL_VALIDATION: "true"
OPENCODE_SOURCE_WORKDIR: ${{ runner.temp }}/noema-pr-head
OPENCODE_CHANGED_FILES_FILE: ${{ runner.temp }}/opencode-changed-files.txt
OPENCODE_ARTIFACT_MANIFEST_SHA256: ${{ steps.primary_approval_evidence.outputs.manifest_sha256 }}
run: |
set -euo pipefail
if [ -z "${PR_NUMBER:-}" ]; then
Expand Down
Loading
Loading