Skip to content
Merged
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
14 changes: 4 additions & 10 deletions .github/aicodingflow-tests/test_codex_model_provider_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,22 @@ def test_all_codex_workflows_use_shared_provider_configuration(self) -> None:
with self.subTest(path=path):
contents = (ROOT / path).read_text(encoding="utf-8")
self.assertEqual(contents.count("uses: openai/codex-action@v1"), 1)
self.assertEqual(
contents.count("openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}"),
1,
)
self.assertEqual(contents.count("openai-api-key: ${{ secrets.CODEX_API_KEY }}"), 1)
self.assertEqual(
contents.count("model: ${{ vars.CODEX_MODEL }}"),
1,
)
self.assertEqual(
contents.count("CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}"),
1,
)
self.assertEqual(contents.count("CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}"), 1)
self.assertIn('endpoint="${CODEX_API_ENDPOINT%/}"', contents)
self.assertIn("*/responses", contents)
self.assertIn("$endpoint/responses", contents)
self.assertIn("CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set", contents)
self.assertIn("CODEX_API_ENDPOINT is not set", contents)

def test_workflows_do_not_read_the_legacy_endpoint_environment_directly(self) -> None:
for path in CODEX_WORKFLOWS:
with self.subTest(path=path):
contents = (ROOT / path).read_text(encoding="utf-8")
self.assertNotIn('endpoint="${OPENAI_API_ENDPOINT%/}"', contents)
self.assertNotIn("OPENAI_", contents)


if __name__ == "__main__":
Expand Down
6 changes: 3 additions & 3 deletions .github/aicodingflow-tests/test_review_workflow_dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def test_review_workflow_resolves_pr_before_checkout_and_uses_normalized_event(s
self.assertIn("cp -R .agents/contracts pr-worktree/.agents/contracts", prepare_step["run"])

ai_step = next(step for step in review_steps if step.get("name") == "Run AI review")
self.assertEqual(ai_step["with"]["allow-bot-users"], "github-actions[bot]")
self.assertIs(ai_step["with"]["allow-bots"], True)
self.assertIn("First change directory to pr-worktree", ai_step["with"]["prompt"])
self.assertIn("Read .agents/contracts/review.md", ai_step["with"]["prompt"])
self.assertIn("shared review contract", ai_step["with"]["prompt"])
Expand Down Expand Up @@ -254,7 +254,7 @@ def test_create_implementation_workflow_does_not_dispatch_review_after_pr_creati
self.assertEqual(app_token["id"], "app-token")
self.assertEqual(app_token["uses"], "actions/create-github-app-token@v3")
self.assertEqual(app_token["if"], commit["if"] + " && steps.workflow_update.outputs.required == 'true'")
self.assertEqual(app_token["with"]["client-id"], "${{ vars.APP_CLIENT_ID }}")
self.assertEqual(app_token["with"]["app-id"], "${{ vars.APP_ID }}")
self.assertEqual(app_token["with"]["private-key"], "${{ secrets.APP_PRIVATE_KEY }}")
self.assertEqual(app_token["with"]["permission-contents"], "write")
self.assertEqual(app_token["with"]["permission-workflows"], "write")
Expand Down Expand Up @@ -451,7 +451,7 @@ def test_respond_to_pr_comment_workflow_has_secure_triggers_and_gates(self) -> N
self.assertEqual(app_token["id"], "app-token")
self.assertEqual(app_token["uses"], "actions/create-github-app-token@v3")
self.assertEqual(app_token["if"], commit["if"] + " && steps.workflow_update.outputs.required == 'true'")
self.assertEqual(app_token["with"]["client-id"], "${{ vars.APP_CLIENT_ID }}")
self.assertEqual(app_token["with"]["app-id"], "${{ vars.APP_ID }}")
self.assertEqual(app_token["with"]["private-key"], "${{ secrets.APP_PRIVATE_KEY }}")
self.assertEqual(app_token["with"]["permission-contents"], "write")
self.assertEqual(app_token["with"]["permission-workflows"], "write")
Expand Down
15 changes: 15 additions & 0 deletions .github/tests/test_ci_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,26 @@ def test_ci_dispatches_review_only_after_tests_pass(self) -> None:
self.assertIn("github.event.pull_request.head.repo.full_name == github.repository", data["jobs"]["ai-review"]["if"])

test_steps = steps(data, "test")
dependencies = next(step for step in test_steps if step.get("name") == "Install Python test dependencies")
self.assertIn('python3 -m venv "$RUNNER_TEMP/aicodingflow-venv"', dependencies["run"])
self.assertIn('aicodingflow-venv/bin/python" -m pip install', dependencies["run"])
self.assertIn('"PyYAML==6.0.3"', dependencies["run"])

project_tests = next(step for step in test_steps if step.get("name") == "Run repository unit tests")
delivery_tests = next(step for step in test_steps if step.get("name") == "Run delivered unit tests")
self.assertIn("python3 -m unittest discover -s .github/tests", project_tests["run"])
self.assertIn("python3 -m unittest discover -s .github/aicodingflow-tests", delivery_tests["run"])

install_actionlint = next(step for step in test_steps if step.get("name") == "Install actionlint")
self.assertEqual(install_actionlint["env"]["ACTIONLINT_VERSION"], "1.7.12")
self.assertIn("sha256sum --check", install_actionlint["run"])

lint_workflows = next(step for step in test_steps if step.get("name") == "Lint GitHub Actions workflows")
self.assertIn("find .github/workflows", lint_workflows["run"])
self.assertIn("-name '*.yml'", lint_workflows["run"])
self.assertIn("-name '*.yaml'", lint_workflows["run"])
self.assertIn('actionlint "${workflow_files[@]}"', lint_workflows["run"])

dispatch_step = next(step for step in steps(data, "ai-review") if step.get("name") == "Dispatch AI PR Review")
self.assertEqual(dispatch_step["env"]["GH_TOKEN"], "${{ github.token }}")
self.assertEqual(dispatch_step["env"]["PR_NUMBER"], "${{ github.event.pull_request.number }}")
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,42 @@ jobs:
with:
fetch-depth: 1

- name: Install Python test dependencies
run: |
python3 -m venv "$RUNNER_TEMP/aicodingflow-venv"
"$RUNNER_TEMP/aicodingflow-venv/bin/python" -m pip install \
--disable-pip-version-check "PyYAML==6.0.3"
echo "$RUNNER_TEMP/aicodingflow-venv/bin" >> "$GITHUB_PATH"

- name: Run repository unit tests
run: python3 -m unittest discover -s .github/tests

- name: Run delivered unit tests
run: python3 -m unittest discover -s .github/aicodingflow-tests

- name: Install actionlint
env:
ACTIONLINT_VERSION: "1.7.12"
run: |
archive="actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
base_url="https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}"
curl --fail --silent --show-error --location "$base_url/$archive" --output "$RUNNER_TEMP/$archive"
curl --fail --silent --show-error --location "$base_url/actionlint_${ACTIONLINT_VERSION}_checksums.txt" \
--output "$RUNNER_TEMP/actionlint_checksums.txt"
grep " $archive$" "$RUNNER_TEMP/actionlint_checksums.txt" > "$RUNNER_TEMP/actionlint_checksum.txt"
(cd "$RUNNER_TEMP" && sha256sum --check actionlint_checksum.txt)
tar -xzf "$RUNNER_TEMP/$archive" -C "$RUNNER_TEMP"
echo "$RUNNER_TEMP" >> "$GITHUB_PATH"

- name: Lint GitHub Actions workflows
run: |
mapfile -d '' workflow_files < <(find .github/workflows -type f \( -name '*.yml' -o -name '*.yaml' \) -print0)
if ((${#workflow_files[@]} == 0)); then
echo "No GitHub Actions workflow files found" >&2
exit 1
fi
actionlint "${workflow_files[@]}"

- name: Compile Python scripts
run: |
PYTHONPYCACHEPREFIX=/tmp/aicodingflow-pycache python3 -m py_compile \
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/create-implementation-from-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,11 @@ jobs:
if: steps.issue.outputs.should_run == 'true' && steps.issue.outputs.should_noop != 'true'
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand Down Expand Up @@ -156,7 +156,7 @@ jobs:
if: steps.issue.outputs.should_run == 'true' && steps.issue.outputs.should_noop != 'true'
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
prompt: |
Expand Down Expand Up @@ -308,7 +308,7 @@ jobs:
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ vars.APP_CLIENT_ID }}
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
permission-contents: write
permission-workflows: write
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/create-spec-from-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ jobs:
if: steps.issue.outputs.should_run == 'true'
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand All @@ -108,7 +108,7 @@ jobs:
if: steps.issue.outputs.should_run == 'true'
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
prompt: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/product-change-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ jobs:
if: steps.context.outputs.reportable_pr_count != '0'
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand All @@ -94,7 +94,7 @@ jobs:
if: steps.context.outputs.reportable_pr_count != '0'
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
prompt: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/product-docs-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,11 @@ jobs:
if: steps.context.outputs.should_run == 'true'
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand All @@ -120,7 +120,7 @@ jobs:
if: steps.context.outputs.should_run == 'true'
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
prompt: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/product-wiki-compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ jobs:
- name: Configure Codex API endpoint
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand All @@ -80,7 +80,7 @@ jobs:
- name: Compile product wiki
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
prompt: |
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/respond-to-pr-comment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,11 @@ jobs:
if: steps.context.outputs.should_run == 'true' && steps.context.outputs.branch_strategy != 'blocked'
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand All @@ -210,7 +210,7 @@ jobs:
if: steps.context.outputs.should_run == 'true' && steps.context.outputs.branch_strategy != 'blocked'
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
prompt: |
Expand Down Expand Up @@ -353,7 +353,7 @@ jobs:
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ vars.APP_CLIENT_ID }}
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.APP_PRIVATE_KEY }}
permission-contents: write
permission-workflows: write
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/review-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,11 @@ jobs:
- name: Configure Codex API endpoint
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand All @@ -192,10 +192,10 @@ jobs:
- name: Run AI review
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
allow-bot-users: github-actions[bot]
allow-bots: true
prompt: |
First change directory to pr-worktree and do all file inspection from there.
Read ${{ steps.review_skill.outputs.path }} in pr-worktree and follow it exactly.
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/triage-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ jobs:
if: steps.issue.outputs.should_run == 'true'
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand All @@ -124,7 +124,7 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
allow-users: "*"
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/update-dedupe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ jobs:
- name: Configure Codex API endpoint
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand All @@ -87,7 +87,7 @@ jobs:
- name: Update local dedupe guidance
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
prompt: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/update-pr-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ jobs:
- name: Configure Codex API endpoint
id: codex_endpoint
env:
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT || vars.OPENAI_API_ENDPOINT }}
CODEX_API_ENDPOINT: ${{ vars.CODEX_API_ENDPOINT }}
run: |
endpoint="${CODEX_API_ENDPOINT%/}"
if [ -z "$endpoint" ]; then
echo "CODEX_API_ENDPOINT or OPENAI_API_ENDPOINT is not set" >&2
echo "CODEX_API_ENDPOINT is not set" >&2
exit 1
fi
case "$endpoint" in
Expand All @@ -101,7 +101,7 @@ jobs:
- name: Update local review guidance
uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.CODEX_API_KEY || secrets.OPENAI_API_KEY }}
openai-api-key: ${{ secrets.CODEX_API_KEY }}
model: ${{ vars.CODEX_MODEL }}
responses-api-endpoint: ${{ steps.codex_endpoint.outputs.url }}
prompt: |
Expand Down
Loading