diff --git a/.github/aw/actions-lock.json b/.github/aw/actions-lock.json index edbd2e8785..2db5179bb9 100644 --- a/.github/aw/actions-lock.json +++ b/.github/aw/actions-lock.json @@ -25,11 +25,6 @@ "version": "v4.3.0", "sha": "0057852bfaa89a56745cba8c7296529d2fc39830" }, - "actions/checkout@v3": { - "repo": "actions/checkout", - "version": "v3", - "sha": "f43a0e5ff2bd294095638e18286ca9a3d1956744" - }, "actions/checkout@v4": { "repo": "actions/checkout", "version": "v4", diff --git a/.github/workflows/archie.lock.yml b/.github/workflows/archie.lock.yml index a55f1e9770..d543ce66c6 100644 --- a/.github/workflows/archie.lock.yml +++ b/.github/workflows/archie.lock.yml @@ -116,6 +116,14 @@ jobs: agent: needs: activation + if: > + (github.event_name == 'issues') && (contains(github.event.issue.body, '/archie')) || + (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/archie')) && (github.event.issue.pull_request == null)) || + (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/archie')) && (github.event.issue.pull_request != null)) || + (github.event_name == 'pull_request') && + (contains(github.event.pull_request.body, '/archie')) runs-on: ubuntu-latest permissions: actions: read diff --git a/.github/workflows/audit-workflows.lock.yml b/.github/workflows/audit-workflows.lock.yml index 08c59d1cd8..215670077b 100644 --- a/.github/workflows/audit-workflows.lock.yml +++ b/.github/workflows/audit-workflows.lock.yml @@ -1575,7 +1575,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/brave.lock.yml b/.github/workflows/brave.lock.yml index 7097d35480..945e06b83d 100644 --- a/.github/workflows/brave.lock.yml +++ b/.github/workflows/brave.lock.yml @@ -105,6 +105,8 @@ jobs: agent: needs: activation + if: > + (github.event_name == 'issue_comment') && ((contains(github.event.comment.body, '/brave')) && (github.event.issue.pull_request == null)) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/changeset.lock.yml b/.github/workflows/changeset.lock.yml index 897740a09c..e480ca58d4 100644 --- a/.github/workflows/changeset.lock.yml +++ b/.github/workflows/changeset.lock.yml @@ -111,6 +111,10 @@ jobs: agent: needs: activation + if: > + ((github.event.pull_request.base.ref == github.event.repository.default_branch) && ((github.event_name != 'pull_request') || + (github.event.pull_request.head.repo.id == github.repository_id))) && ((github.event_name != 'pull_request') || + ((github.event.action != 'labeled') || (github.event.label.name == 'changeset' || github.event.label.name == 'smoke'))) runs-on: ubuntu-latest permissions: contents: read @@ -1344,14 +1348,14 @@ jobs: permission-issues: write permission-pull-requests: write - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ steps.safe-outputs-app-token.outputs.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/ci-coach.lock.yml b/.github/workflows/ci-coach.lock.yml index d16c9c5a69..f461081c46 100644 --- a/.github/workflows/ci-coach.lock.yml +++ b/.github/workflows/ci-coach.lock.yml @@ -1564,14 +1564,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/ci-doctor.lock.yml b/.github/workflows/ci-doctor.lock.yml index 5655fbd5c3..0789ed8ed4 100644 --- a/.github/workflows/ci-doctor.lock.yml +++ b/.github/workflows/ci-doctor.lock.yml @@ -84,6 +84,7 @@ jobs: agent: needs: activation + if: ${{ github.event.workflow_run.conclusion == 'failure' }} runs-on: ubuntu-latest permissions: actions: read diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml index f4882af4f7..5f2c6ed018 100644 --- a/.github/workflows/cloclo.lock.yml +++ b/.github/workflows/cloclo.lock.yml @@ -142,6 +142,22 @@ jobs: agent: needs: activation + if: > + (((github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request' || + github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment') && + ((github.event_name == 'issues') && (contains(github.event.issue.body, '/cloclo')) || (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/cloclo')) && (github.event.issue.pull_request == null)) || + (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/cloclo')) && (github.event.issue.pull_request != null)) || + (github.event_name == 'pull_request_review_comment') && + (contains(github.event.comment.body, '/cloclo')) || (github.event_name == 'pull_request') && + (contains(github.event.pull_request.body, '/cloclo')) || + (github.event_name == 'discussion') && (contains(github.event.discussion.body, '/cloclo')) || + (github.event_name == 'discussion_comment') && + (contains(github.event.comment.body, '/cloclo')))) || (!(github.event_name == 'issues' || github.event_name == 'issue_comment' || + github.event_name == 'pull_request' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || + github.event_name == 'discussion_comment'))) && ((github.event_name != 'issues') || ((github.event.action != 'labeled') || + (github.event.label.name == 'cloclo'))) runs-on: ubuntu-latest permissions: actions: read @@ -1530,14 +1546,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/code-scanning-fixer.lock.yml b/.github/workflows/code-scanning-fixer.lock.yml index 48d72075ca..6fbd00d57f 100644 --- a/.github/workflows/code-scanning-fixer.lock.yml +++ b/.github/workflows/code-scanning-fixer.lock.yml @@ -1265,14 +1265,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/code-simplifier.lock.yml b/.github/workflows/code-simplifier.lock.yml index ba595bfe40..e953505c80 100644 --- a/.github/workflows/code-simplifier.lock.yml +++ b/.github/workflows/code-simplifier.lock.yml @@ -1185,14 +1185,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/copilot-pr-nlp-analysis.lock.yml b/.github/workflows/copilot-pr-nlp-analysis.lock.yml index be5ba26fae..832c3a3b32 100644 --- a/.github/workflows/copilot-pr-nlp-analysis.lock.yml +++ b/.github/workflows/copilot-pr-nlp-analysis.lock.yml @@ -1695,7 +1695,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/copilot-session-insights.lock.yml b/.github/workflows/copilot-session-insights.lock.yml index 8a4b07d536..fdcb41dae0 100644 --- a/.github/workflows/copilot-session-insights.lock.yml +++ b/.github/workflows/copilot-session-insights.lock.yml @@ -2091,7 +2091,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/craft.lock.yml b/.github/workflows/craft.lock.yml index f5ef68c7e8..98c7431e12 100644 --- a/.github/workflows/craft.lock.yml +++ b/.github/workflows/craft.lock.yml @@ -102,6 +102,7 @@ jobs: agent: needs: activation + if: (github.event_name == 'issues') && (contains(github.event.issue.body, '/craft')) runs-on: ubuntu-latest permissions: contents: read @@ -1167,14 +1168,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/daily-choice-test.lock.yml b/.github/workflows/daily-choice-test.lock.yml index 451d0ec6d0..1245a75328 100644 --- a/.github/workflows/daily-choice-test.lock.yml +++ b/.github/workflows/daily-choice-test.lock.yml @@ -1089,7 +1089,7 @@ jobs: - agent - detection if: > - ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'test_environment')) + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'test_environment')) runs-on: ubuntu-latest steps: - name: Download agent output artifact diff --git a/.github/workflows/daily-code-metrics.lock.yml b/.github/workflows/daily-code-metrics.lock.yml index 1fe5822a42..9a2983d825 100644 --- a/.github/workflows/daily-code-metrics.lock.yml +++ b/.github/workflows/daily-code-metrics.lock.yml @@ -1836,7 +1836,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/daily-copilot-token-report.lock.yml b/.github/workflows/daily-copilot-token-report.lock.yml index e465053cfa..4834a58c4b 100644 --- a/.github/workflows/daily-copilot-token-report.lock.yml +++ b/.github/workflows/daily-copilot-token-report.lock.yml @@ -1610,7 +1610,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/daily-doc-updater.lock.yml b/.github/workflows/daily-doc-updater.lock.yml index 6879a539b6..c4f8c6cbab 100644 --- a/.github/workflows/daily-doc-updater.lock.yml +++ b/.github/workflows/daily-doc-updater.lock.yml @@ -1176,14 +1176,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/daily-firewall-report.lock.yml b/.github/workflows/daily-firewall-report.lock.yml index fd1d8f8cc6..d79938c1dd 100644 --- a/.github/workflows/daily-firewall-report.lock.yml +++ b/.github/workflows/daily-firewall-report.lock.yml @@ -1324,7 +1324,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/daily-issues-report.lock.yml b/.github/workflows/daily-issues-report.lock.yml index bf65fe2362..ebb0d70af4 100644 --- a/.github/workflows/daily-issues-report.lock.yml +++ b/.github/workflows/daily-issues-report.lock.yml @@ -1938,7 +1938,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/daily-multi-device-docs-tester.lock.yml b/.github/workflows/daily-multi-device-docs-tester.lock.yml index 9d6513d6ce..68609ae942 100644 --- a/.github/workflows/daily-multi-device-docs-tester.lock.yml +++ b/.github/workflows/daily-multi-device-docs-tester.lock.yml @@ -1379,7 +1379,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/daily-news.lock.yml b/.github/workflows/daily-news.lock.yml index 39e5bd366d..ec3f8b678e 100644 --- a/.github/workflows/daily-news.lock.yml +++ b/.github/workflows/daily-news.lock.yml @@ -1945,7 +1945,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/daily-performance-summary.lock.yml b/.github/workflows/daily-performance-summary.lock.yml index 7f0882c3d5..21d43ecb97 100644 --- a/.github/workflows/daily-performance-summary.lock.yml +++ b/.github/workflows/daily-performance-summary.lock.yml @@ -1830,7 +1830,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/daily-repo-chronicle.lock.yml b/.github/workflows/daily-repo-chronicle.lock.yml index a824a8e6a4..82dadc5533 100644 --- a/.github/workflows/daily-repo-chronicle.lock.yml +++ b/.github/workflows/daily-repo-chronicle.lock.yml @@ -1663,7 +1663,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/daily-workflow-updater.lock.yml b/.github/workflows/daily-workflow-updater.lock.yml index dece30fb3f..335e9aa98f 100644 --- a/.github/workflows/daily-workflow-updater.lock.yml +++ b/.github/workflows/daily-workflow-updater.lock.yml @@ -1090,14 +1090,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/deep-report.lock.yml b/.github/workflows/deep-report.lock.yml index ee18dfee4d..690e3b10e4 100644 --- a/.github/workflows/deep-report.lock.yml +++ b/.github/workflows/deep-report.lock.yml @@ -1622,7 +1622,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/dependabot-bundler.lock.yml b/.github/workflows/dependabot-bundler.lock.yml index 974a7d0648..1baa531a40 100644 --- a/.github/workflows/dependabot-bundler.lock.yml +++ b/.github/workflows/dependabot-bundler.lock.yml @@ -1265,14 +1265,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/dev-hawk.lock.yml b/.github/workflows/dev-hawk.lock.yml index 00873f95b5..78c0b2e08c 100644 --- a/.github/workflows/dev-hawk.lock.yml +++ b/.github/workflows/dev-hawk.lock.yml @@ -83,6 +83,7 @@ jobs: agent: needs: activation + if: ${{ github.event.workflow_run.event == 'workflow_dispatch' }} runs-on: ubuntu-latest permissions: actions: read diff --git a/.github/workflows/dev.lock.yml b/.github/workflows/dev.lock.yml index 020da4e1a6..fc816529d2 100644 --- a/.github/workflows/dev.lock.yml +++ b/.github/workflows/dev.lock.yml @@ -1053,14 +1053,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml index 50983a97ee..6d3a7745f1 100644 --- a/.github/workflows/developer-docs-consolidator.lock.yml +++ b/.github/workflows/developer-docs-consolidator.lock.yml @@ -1319,14 +1319,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/dictation-prompt.lock.yml b/.github/workflows/dictation-prompt.lock.yml index 4fecb9c19e..88e34c16a9 100644 --- a/.github/workflows/dictation-prompt.lock.yml +++ b/.github/workflows/dictation-prompt.lock.yml @@ -1132,14 +1132,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/docs-noob-tester.lock.yml b/.github/workflows/docs-noob-tester.lock.yml index 25ddb71285..bccc34d10c 100644 --- a/.github/workflows/docs-noob-tester.lock.yml +++ b/.github/workflows/docs-noob-tester.lock.yml @@ -1159,7 +1159,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/firewall-escape.lock.yml b/.github/workflows/firewall-escape.lock.yml index 4343b6d4c2..5f26cd725d 100644 --- a/.github/workflows/firewall-escape.lock.yml +++ b/.github/workflows/firewall-escape.lock.yml @@ -80,6 +80,9 @@ jobs: agent: needs: activation + if: > + ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id)) && + ((github.event_name != 'pull_request') || ((github.event.action != 'labeled') || (github.event.label.name == 'firewall-escape-test'))) runs-on: ubuntu-latest permissions: actions: read diff --git a/.github/workflows/github-mcp-structural-analysis.lock.yml b/.github/workflows/github-mcp-structural-analysis.lock.yml index 5ef85c98cf..b0e9564b0b 100644 --- a/.github/workflows/github-mcp-structural-analysis.lock.yml +++ b/.github/workflows/github-mcp-structural-analysis.lock.yml @@ -1555,7 +1555,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/github-mcp-tools-report.lock.yml b/.github/workflows/github-mcp-tools-report.lock.yml index 2cd5aa54f7..b85046fe25 100644 --- a/.github/workflows/github-mcp-tools-report.lock.yml +++ b/.github/workflows/github-mcp-tools-report.lock.yml @@ -1281,14 +1281,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml index f0b5a59951..0eaf87840e 100644 --- a/.github/workflows/glossary-maintainer.lock.yml +++ b/.github/workflows/glossary-maintainer.lock.yml @@ -1631,14 +1631,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/go-logger.lock.yml b/.github/workflows/go-logger.lock.yml index c39d135a6c..d7a46836bc 100644 --- a/.github/workflows/go-logger.lock.yml +++ b/.github/workflows/go-logger.lock.yml @@ -1359,14 +1359,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/go-pattern-detector.lock.yml b/.github/workflows/go-pattern-detector.lock.yml index 65a6095871..5db6f49bde 100644 --- a/.github/workflows/go-pattern-detector.lock.yml +++ b/.github/workflows/go-pattern-detector.lock.yml @@ -74,7 +74,6 @@ jobs: needs: - activation - ast_grep - if: needs.ast_grep.outputs.found_patterns == 'true' runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/grumpy-reviewer.lock.yml b/.github/workflows/grumpy-reviewer.lock.yml index ffa1982a16..551621e027 100644 --- a/.github/workflows/grumpy-reviewer.lock.yml +++ b/.github/workflows/grumpy-reviewer.lock.yml @@ -106,6 +106,9 @@ jobs: agent: needs: activation + if: > + (github.event_name == 'issue_comment') && ((contains(github.event.comment.body, '/grumpy')) && (github.event.issue.pull_request != null)) || + (github.event_name == 'pull_request_review_comment') && (contains(github.event.comment.body, '/grumpy')) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/hourly-ci-cleaner.lock.yml b/.github/workflows/hourly-ci-cleaner.lock.yml index e98534ca66..328631e7c9 100644 --- a/.github/workflows/hourly-ci-cleaner.lock.yml +++ b/.github/workflows/hourly-ci-cleaner.lock.yml @@ -74,7 +74,6 @@ jobs: needs: - activation - check_ci_status - if: needs.check_ci_status.outputs.ci_needs_fix == 'true' runs-on: ubuntu-latest permissions: actions: read @@ -1439,14 +1438,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/instructions-janitor.lock.yml b/.github/workflows/instructions-janitor.lock.yml index b28b007944..34be466f21 100644 --- a/.github/workflows/instructions-janitor.lock.yml +++ b/.github/workflows/instructions-janitor.lock.yml @@ -1170,14 +1170,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/issue-monster.lock.yml b/.github/workflows/issue-monster.lock.yml index 474cfe7bd2..15f90724e0 100644 --- a/.github/workflows/issue-monster.lock.yml +++ b/.github/workflows/issue-monster.lock.yml @@ -1142,7 +1142,7 @@ jobs: await main(); - name: Assign To Agent id: assign_to_agent - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'assign_to_agent')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'assign_to_agent')) uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} diff --git a/.github/workflows/jsweep.lock.yml b/.github/workflows/jsweep.lock.yml index b2f52cfe61..1abb2be4e6 100644 --- a/.github/workflows/jsweep.lock.yml +++ b/.github/workflows/jsweep.lock.yml @@ -1103,14 +1103,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/layout-spec-maintainer.lock.yml b/.github/workflows/layout-spec-maintainer.lock.yml index ba029a5622..05032ce60a 100644 --- a/.github/workflows/layout-spec-maintainer.lock.yml +++ b/.github/workflows/layout-spec-maintainer.lock.yml @@ -1099,14 +1099,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/mcp-inspector.lock.yml b/.github/workflows/mcp-inspector.lock.yml index 09fc25e978..d4e6560e55 100644 --- a/.github/workflows/mcp-inspector.lock.yml +++ b/.github/workflows/mcp-inspector.lock.yml @@ -1610,7 +1610,7 @@ jobs: - agent - detection if: > - ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'notion_add_comment')) + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'notion_add_comment')) runs-on: ubuntu-latest permissions: contents: read @@ -1740,7 +1740,7 @@ jobs: - agent - detection if: > - ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'post_to_slack_channel')) + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'post_to_slack_channel')) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/mergefest.lock.yml b/.github/workflows/mergefest.lock.yml index 272bb1daaa..8d32530412 100644 --- a/.github/workflows/mergefest.lock.yml +++ b/.github/workflows/mergefest.lock.yml @@ -90,6 +90,8 @@ jobs: agent: needs: activation + if: > + (github.event_name == 'issue_comment') && ((contains(github.event.comment.body, '/mergefest')) && (github.event.issue.pull_request != null)) runs-on: ubuntu-latest permissions: actions: read @@ -1154,14 +1156,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/notion-issue-summary.lock.yml b/.github/workflows/notion-issue-summary.lock.yml index 117324208b..d737f37ddd 100644 --- a/.github/workflows/notion-issue-summary.lock.yml +++ b/.github/workflows/notion-issue-summary.lock.yml @@ -980,7 +980,7 @@ jobs: - agent - detection if: > - ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'notion_add_comment')) + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'notion_add_comment')) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/org-health-report.lock.yml b/.github/workflows/org-health-report.lock.yml index 7063ef5e72..e89c5a6075 100644 --- a/.github/workflows/org-health-report.lock.yml +++ b/.github/workflows/org-health-report.lock.yml @@ -1565,7 +1565,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/pdf-summary.lock.yml b/.github/workflows/pdf-summary.lock.yml index 6337cafc91..2636d2d2d4 100644 --- a/.github/workflows/pdf-summary.lock.yml +++ b/.github/workflows/pdf-summary.lock.yml @@ -124,6 +124,11 @@ jobs: agent: needs: activation + if: > + ((github.event_name == 'issue_comment' || github.event_name == 'issues') && ((github.event_name == 'issues') && + (contains(github.event.issue.body, '/summarize')) || (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/summarize')) && + (github.event.issue.pull_request == null)))) || (!(github.event_name == 'issue_comment' || github.event_name == 'issues')) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/plan.lock.yml b/.github/workflows/plan.lock.yml index bd9f35ca87..05517868c4 100644 --- a/.github/workflows/plan.lock.yml +++ b/.github/workflows/plan.lock.yml @@ -105,6 +105,9 @@ jobs: agent: needs: activation + if: > + (github.event_name == 'issue_comment') && ((contains(github.event.comment.body, '/plan')) && (github.event.issue.pull_request == null)) || + (github.event_name == 'discussion_comment') && (contains(github.event.comment.body, '/plan')) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/poem-bot.lock.yml b/.github/workflows/poem-bot.lock.yml index 5162cfd9b1..f3410565b0 100644 --- a/.github/workflows/poem-bot.lock.yml +++ b/.github/workflows/poem-bot.lock.yml @@ -113,6 +113,9 @@ jobs: agent: needs: activation + if: > + ((github.event_name == 'issues') && ((github.event_name == 'issues') && (contains(github.event.issue.body, '/poem-bot')))) || + (!(github.event_name == 'issues')) runs-on: ubuntu-latest permissions: contents: read @@ -1839,14 +1842,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: (((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))) || (((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch'))) + if: ((((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))) || ((((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch'))) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: (((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))) || (((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch'))) + if: ((((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))) || ((((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch'))) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} @@ -1874,7 +1877,7 @@ jobs: await main(); - name: Create Agent Session id: create_agent_session - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_agent_session')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_agent_session')) uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} @@ -1921,7 +1924,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/portfolio-analyst.lock.yml b/.github/workflows/portfolio-analyst.lock.yml index 5b15f9ceab..35559df913 100644 --- a/.github/workflows/portfolio-analyst.lock.yml +++ b/.github/workflows/portfolio-analyst.lock.yml @@ -1406,7 +1406,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/pr-nitpick-reviewer.lock.yml b/.github/workflows/pr-nitpick-reviewer.lock.yml index 6a87315214..344405c31a 100644 --- a/.github/workflows/pr-nitpick-reviewer.lock.yml +++ b/.github/workflows/pr-nitpick-reviewer.lock.yml @@ -126,6 +126,17 @@ jobs: agent: needs: activation + if: > + (github.event_name == 'issues') && (contains(github.event.issue.body, '/nit')) || (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/nit')) && (github.event.issue.pull_request == null)) || + (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/nit')) && (github.event.issue.pull_request != null)) || + (github.event_name == 'pull_request_review_comment') && + (contains(github.event.comment.body, '/nit')) || (github.event_name == 'pull_request') && + (contains(github.event.pull_request.body, '/nit')) || + (github.event_name == 'discussion') && (contains(github.event.discussion.body, '/nit')) || + (github.event_name == 'discussion_comment') && + (contains(github.event.comment.body, '/nit')) runs-on: ubuntu-latest permissions: actions: read diff --git a/.github/workflows/python-data-charts.lock.yml b/.github/workflows/python-data-charts.lock.yml index 009a9cb1d9..f84dd9c391 100644 --- a/.github/workflows/python-data-charts.lock.yml +++ b/.github/workflows/python-data-charts.lock.yml @@ -2025,7 +2025,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index cee0e3a0d6..ffee51ebb0 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -136,6 +136,17 @@ jobs: agent: needs: activation + if: > + (github.event_name == 'issues') && (contains(github.event.issue.body, '/q')) || (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/q')) && (github.event.issue.pull_request == null)) || + (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/q')) && (github.event.issue.pull_request != null)) || + (github.event_name == 'pull_request_review_comment') && + (contains(github.event.comment.body, '/q')) || (github.event_name == 'pull_request') && + (contains(github.event.pull_request.body, '/q')) || + (github.event_name == 'discussion') && (contains(github.event.discussion.body, '/q')) || + (github.event_name == 'discussion_comment') && + (contains(github.event.comment.body, '/q')) runs-on: ubuntu-latest permissions: actions: read @@ -1300,14 +1311,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/scout.lock.yml b/.github/workflows/scout.lock.yml index 0ae4e67563..403fb0aa2d 100644 --- a/.github/workflows/scout.lock.yml +++ b/.github/workflows/scout.lock.yml @@ -151,6 +151,21 @@ jobs: agent: needs: activation + if: > + ((github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request' || + github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment') && + ((github.event_name == 'issues') && (contains(github.event.issue.body, '/scout')) || (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/scout')) && (github.event.issue.pull_request == null)) || + (github.event_name == 'issue_comment') && + ((contains(github.event.comment.body, '/scout')) && (github.event.issue.pull_request != null)) || + (github.event_name == 'pull_request_review_comment') && + (contains(github.event.comment.body, '/scout')) || (github.event_name == 'pull_request') && + (contains(github.event.pull_request.body, '/scout')) || + (github.event_name == 'discussion') && (contains(github.event.discussion.body, '/scout')) || + (github.event_name == 'discussion_comment') && + (contains(github.event.comment.body, '/scout')))) || (!(github.event_name == 'issues' || github.event_name == 'issue_comment' || + github.event_name == 'pull_request' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || + github.event_name == 'discussion_comment')) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/secret-scanning-triage.lock.yml b/.github/workflows/secret-scanning-triage.lock.yml index d2fe41b10f..8379db4578 100644 --- a/.github/workflows/secret-scanning-triage.lock.yml +++ b/.github/workflows/secret-scanning-triage.lock.yml @@ -1370,14 +1370,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/security-guard.lock.yml b/.github/workflows/security-guard.lock.yml index df52c64121..559df766e6 100644 --- a/.github/workflows/security-guard.lock.yml +++ b/.github/workflows/security-guard.lock.yml @@ -75,6 +75,10 @@ jobs: agent: needs: activation + if: > + ((github.event_name != 'pull_request') || (github.event.pull_request.draft == false)) && + ((github.event_name != 'pull_request') || + (github.event.pull_request.head.repo.id == github.repository_id)) runs-on: ubuntu-latest permissions: actions: read diff --git a/.github/workflows/security-review.lock.yml b/.github/workflows/security-review.lock.yml index 47d46a8776..0e121364d7 100644 --- a/.github/workflows/security-review.lock.yml +++ b/.github/workflows/security-review.lock.yml @@ -107,6 +107,10 @@ jobs: agent: needs: activation + if: > + (github.event_name == 'issue_comment') && ((contains(github.event.comment.body, '/security-review')) && + (github.event.issue.pull_request != null)) || (github.event_name == 'pull_request_review_comment') && + (contains(github.event.comment.body, '/security-review')) runs-on: ubuntu-latest permissions: actions: read diff --git a/.github/workflows/slide-deck-maintainer.lock.yml b/.github/workflows/slide-deck-maintainer.lock.yml index e1b37ca6f4..b7a84f3d00 100644 --- a/.github/workflows/slide-deck-maintainer.lock.yml +++ b/.github/workflows/slide-deck-maintainer.lock.yml @@ -1193,14 +1193,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index f50a134485..5ac24fc286 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -106,6 +106,9 @@ jobs: agent: needs: activation + if: > + ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id)) && + ((github.event_name != 'pull_request') || ((github.event.action != 'labeled') || (github.event.label.name == 'smoke'))) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/smoke-codex.lock.yml b/.github/workflows/smoke-codex.lock.yml index a7fedb8743..eebe678422 100644 --- a/.github/workflows/smoke-codex.lock.yml +++ b/.github/workflows/smoke-codex.lock.yml @@ -103,6 +103,9 @@ jobs: agent: needs: activation + if: > + ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id)) && + ((github.event_name != 'pull_request') || ((github.event.action != 'labeled') || (github.event.label.name == 'smoke'))) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/smoke-copilot.lock.yml b/.github/workflows/smoke-copilot.lock.yml index 8b4c86d1cb..a23de4a1da 100644 --- a/.github/workflows/smoke-copilot.lock.yml +++ b/.github/workflows/smoke-copilot.lock.yml @@ -102,6 +102,9 @@ jobs: agent: needs: activation + if: > + ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id)) && + ((github.event_name != 'pull_request') || ((github.event.action != 'labeled') || (github.event.label.name == 'smoke'))) runs-on: ubuntu-latest permissions: actions: read @@ -1945,7 +1948,7 @@ jobs: - agent - detection if: > - ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'send_slack_message')) + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'send_slack_message')) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/smoke-opencode.lock.yml b/.github/workflows/smoke-opencode.lock.yml index 35fa8adf8b..a9df97fe82 100644 --- a/.github/workflows/smoke-opencode.lock.yml +++ b/.github/workflows/smoke-opencode.lock.yml @@ -102,6 +102,9 @@ jobs: agent: needs: activation + if: > + ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id)) && + ((github.event_name != 'pull_request') || ((github.event.action != 'labeled') || (github.event.label.name == 'smoke'))) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/smoke-test-tools.lock.yml b/.github/workflows/smoke-test-tools.lock.yml index d05893e063..53a2b0dc80 100644 --- a/.github/workflows/smoke-test-tools.lock.yml +++ b/.github/workflows/smoke-test-tools.lock.yml @@ -80,6 +80,9 @@ jobs: agent: needs: activation + if: > + ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.id == github.repository_id)) && + ((github.event_name != 'pull_request') || ((github.event.action != 'labeled') || (github.event.label.name == 'smoke'))) runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index 8e812f84c0..1b5de17c3f 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -1603,7 +1603,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml index 6f54bbb08f..703229c7b3 100644 --- a/.github/workflows/technical-doc-writer.lock.yml +++ b/.github/workflows/technical-doc-writer.lock.yml @@ -1700,14 +1700,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} @@ -1768,7 +1768,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/test-create-pr-error-handling.lock.yml b/.github/workflows/test-create-pr-error-handling.lock.yml index 81b5e96225..25689e9500 100644 --- a/.github/workflows/test-create-pr-error-handling.lock.yml +++ b/.github/workflows/test-create-pr-error-handling.lock.yml @@ -1144,14 +1144,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 57f96dcedb..4a068a84d9 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -103,6 +103,9 @@ jobs: agent: needs: activation + if: > + ((github.event_name == 'issue_comment') && ((github.event_name == 'issue_comment') && ((contains(github.event.comment.body, '/tidy')) && + (github.event.issue.pull_request != null)))) || (!(github.event_name == 'issue_comment')) runs-on: ubuntu-latest permissions: contents: read @@ -1243,14 +1246,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: (((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))) || (((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch'))) + if: ((((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))) || ((((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch'))) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: (((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))) || (((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch'))) + if: ((((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))) || ((((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch'))) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/ubuntu-image-analyzer.lock.yml b/.github/workflows/ubuntu-image-analyzer.lock.yml index 14b0686d04..08e5370d6e 100644 --- a/.github/workflows/ubuntu-image-analyzer.lock.yml +++ b/.github/workflows/ubuntu-image-analyzer.lock.yml @@ -1134,14 +1134,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index a34b6667d6..50c26aa9ff 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -100,6 +100,9 @@ jobs: agent: needs: activation + if: > + ((github.event_name == 'issue_comment') && ((github.event_name == 'issue_comment') && ((contains(github.event.comment.body, '/unbloat')) && + (github.event.issue.pull_request != null)))) || (!(github.event_name == 'issue_comment')) runs-on: ubuntu-latest permissions: contents: read @@ -1547,14 +1550,14 @@ jobs: name: agent-artifacts path: /tmp/gh-aw/ - name: Checkout repository - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6 with: token: ${{ github.token }} persist-credentials: false fetch-depth: 1 - name: Configure Git credentials - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'create_pull_request')) env: REPO_NAME: ${{ github.repository }} SERVER_URL: ${{ github.server_url }} @@ -1615,7 +1618,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/weekly-issue-summary.lock.yml b/.github/workflows/weekly-issue-summary.lock.yml index d190f14a56..105f1979db 100644 --- a/.github/workflows/weekly-issue-summary.lock.yml +++ b/.github/workflows/weekly-issue-summary.lock.yml @@ -1644,7 +1644,8 @@ jobs: needs: - agent - detection - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) + if: > + (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'upload_asset')) runs-on: ubuntu-slim permissions: contents: write diff --git a/.github/workflows/workflow-generator.lock.yml b/.github/workflows/workflow-generator.lock.yml index ce8319d273..e2d235e567 100644 --- a/.github/workflows/workflow-generator.lock.yml +++ b/.github/workflows/workflow-generator.lock.yml @@ -101,6 +101,7 @@ jobs: agent: needs: activation + if: startsWith(github.event.issue.title, '[Workflow]') runs-on: ubuntu-latest permissions: contents: read @@ -1221,7 +1222,7 @@ jobs: await main(); - name: Assign To Agent id: assign_to_agent - if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'assign_to_agent')) + if: (((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'assign_to_agent')) uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }} diff --git a/pkg/cli/add_interactive_workflow_test.go b/pkg/cli/add_interactive_workflow_test.go index b67aeb2e7f..a3ffce8e90 100644 --- a/pkg/cli/add_interactive_workflow_test.go +++ b/pkg/cli/add_interactive_workflow_test.go @@ -44,12 +44,14 @@ func TestGetWorkflowStatuses(t *testing.T) { statuses, err := getWorkflowStatuses(tt.pattern, tt.repoOverride, tt.verbose) // Either succeeds or fails gracefully, but shouldn't panic - if err == nil { - assert.NotNil(t, statuses, "Statuses should not be nil on success") - } else { + // Note: statuses can be nil even on success (when workflow not found), + // so we only check that error handling is consistent + if err != nil { // Error is acceptable in test environment without gh CLI setup - assert.Error(t, err, "Expected error without gh CLI") + assert.Nil(t, statuses, "Statuses should be nil on error") } + // If err == nil, statuses may be nil (workflow not found) or non-nil (workflow found) + // Both are valid outcomes - the function completed without error }) } } diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 3aaffaf05e..d1a247c26b 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -526,6 +526,12 @@ const SkipCheckOkOutput = "skip_check_ok" const SkipNoMatchCheckOkOutput = "skip_no_match_check_ok" const CommandPositionOkOutput = "command_position_ok" const MatchedCommandOutput = "matched_command" + +// ActivatedOutput is the output name for job activation status. +// The pre_activation job always emits this output to indicate whether the workflow should proceed. +// When preActivationCanBeSkipped is true, other jobs (activation, agent) also emit this output +// so downstream jobs can use always() && !cancelled() combined with checking this output. +// When preActivationCanBeSkipped is false, only pre_activation emits this output. const ActivatedOutput = "activated" // Agentic engine name constants using EngineName type for type safety diff --git a/pkg/workflow/branch_normalize_integration_test.go b/pkg/workflow/branch_normalize_integration_test.go index e92279ae77..70d7caf2c6 100644 --- a/pkg/workflow/branch_normalize_integration_test.go +++ b/pkg/workflow/branch_normalize_integration_test.go @@ -29,7 +29,7 @@ func TestBranchNormalizationInlinedInMainJob(t *testing.T) { } // Build the main job - job, err := compiler.buildMainJob(data, false) + job, err := compiler.buildMainJob(data, false, false) if err != nil { t.Fatalf("Failed to build main job: %v", err) } @@ -66,7 +66,7 @@ func TestBranchNormalizationStepNotAddedWhenNoUploadAssets(t *testing.T) { } // Build the main job - job, err := compiler.buildMainJob(data, false) + job, err := compiler.buildMainJob(data, false, false) if err != nil { t.Fatalf("Failed to build main job: %v", err) } diff --git a/pkg/workflow/compiler_activation_jobs.go b/pkg/workflow/compiler_activation_jobs.go index 15ab28b95c..059e1764a3 100644 --- a/pkg/workflow/compiler_activation_jobs.go +++ b/pkg/workflow/compiler_activation_jobs.go @@ -23,22 +23,24 @@ func containsRole(roles []string, role string) bool { } // buildPreActivationJob creates a unified pre-activation job that combines membership checks and stop-time validation. -// This job exposes a single "activated" output that indicates whether the workflow should proceed. -func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionCheck bool) (*Job, error) { - compilerActivationJobsLog.Printf("Building pre-activation job: needsPermissionCheck=%v, hasStopTime=%v", needsPermissionCheck, data.StopTime != "") +// This job exposes a single "success" output that indicates whether the workflow should proceed. +// Returns the job and a boolean indicating whether the job's "if" condition can cause it to be skipped. +// When preActivationCanBeSkipped is true, downstream jobs must use always() && !cancelled() patterns. +func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionCheck bool, hasRealCustomJobs bool) (*Job, bool, error) { + compilerActivationJobsLog.Printf("Building pre-activation job: needsPermissionCheck=%v, hasStopTime=%v, hasRealCustomJobs=%v", needsPermissionCheck, data.StopTime != "", hasRealCustomJobs) var steps []string var permissions string // Extract custom steps and outputs from jobs.pre-activation if present customSteps, customOutputs, err := c.extractPreActivationCustomFields(data.Jobs) if err != nil { - return nil, fmt.Errorf("failed to extract pre-activation custom fields: %w", err) + return nil, false, fmt.Errorf("failed to extract pre-activation custom fields: %w", err) } // Add setup step to copy activation scripts (required - no inline fallback) setupActionRef := c.resolveActionReference("./actions/setup", data) if setupActionRef == "" { - return nil, fmt.Errorf("setup action reference is required but could not be resolved") + return nil, false, fmt.Errorf("setup action reference is required but could not be resolved") } // For dev mode (local action path), checkout the actions folder first @@ -230,7 +232,7 @@ func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionChec if len(conditions) == 0 { // This should never happen - it means pre-activation job was created without any checks // If we reach this point, it's a developer error in the compiler logic - return nil, fmt.Errorf("developer error: pre-activation job created without permission check or stop-time configuration") + return nil, false, fmt.Errorf("developer error: pre-activation job created without permission check or stop-time configuration") } else if len(conditions) == 1 { // Single condition activatedNode = conditions[0] @@ -246,7 +248,7 @@ func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionChec activatedExpression := fmt.Sprintf("${{ %s }}", activatedNode.Render()) outputs := map[string]string{ - "activated": activatedExpression, + constants.ActivatedOutput: activatedExpression, } // Add matched_command output if this is a command workflow @@ -277,6 +279,7 @@ func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionChec // - skip-if-match: query-based skip applies to all events // - skip-if-no-match: query-based skip applies to all events // - custom steps: user-defined steps may have important logic + // - real custom jobs: having custom jobs makes skip patterns too complex // // Safe events that can skip pre_activation: // - schedule: Triggered by cron, runs as the repository, not user-initiated @@ -284,12 +287,17 @@ func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionChec // - workflow_dispatch: Can skip IF roles include "write" (which the default roles do) // because check_membership.cjs already short-circuits for workflow_dispatch when write is allowed // - // When pre_activation is skipped, downstream jobs check for needs.pre_activation.result == 'skipped' + // When pre_activation is skipped, downstream jobs must use always() && !cancelled() patterns + // to check for needs.pre_activation.result == 'skipped' canSkipForSafeEvents := c.skipPreActivationWithIfOptimization && data.StopTime == "" && data.SkipIfMatch == nil && data.SkipIfNoMatch == nil && - len(customSteps) == 0 + len(customSteps) == 0 && + !hasRealCustomJobs // Disable skip optimization when there are custom jobs + + // Track whether pre_activation can actually be skipped (for downstream job conditions) + preActivationCanBeSkipped := false if canSkipForSafeEvents { // Check if workflow_dispatch can also be skipped (when roles include "write") @@ -303,10 +311,11 @@ func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionChec } else { jobIfCondition = safeEventSkipCondition } + preActivationCanBeSkipped = true compilerActivationJobsLog.Printf("Pre-activation job can be skipped for safe events (rolesIncludeWrite=%v)", rolesIncludeWrite) } else { - compilerActivationJobsLog.Printf("Pre-activation job cannot be skipped for safe events: hasStopTime=%v, hasSkipIfMatch=%v, hasSkipIfNoMatch=%v, hasCustomSteps=%v", - data.StopTime != "", data.SkipIfMatch != nil, data.SkipIfNoMatch != nil, len(customSteps) > 0) + compilerActivationJobsLog.Printf("Pre-activation job cannot be skipped for safe events: hasStopTime=%v, hasSkipIfMatch=%v, hasSkipIfNoMatch=%v, hasCustomSteps=%v, hasRealCustomJobs=%v", + data.StopTime != "", data.SkipIfMatch != nil, data.SkipIfNoMatch != nil, len(customSteps) > 0, hasRealCustomJobs) } job := &Job{ @@ -318,7 +327,7 @@ func (c *Compiler) buildPreActivationJob(data *WorkflowData, needsPermissionChec Outputs: outputs, } - return job, nil + return job, preActivationCanBeSkipped, nil } // extractPreActivationCustomFields extracts custom steps and outputs from jobs.pre-activation field in frontmatter. @@ -411,7 +420,9 @@ func (c *Compiler) extractPreActivationCustomFields(jobs map[string]any) ([]stri // buildActivationJob creates the activation job that handles timestamp checking, reactions, and locking. // This job depends on the pre-activation job if it exists, and runs before the main agent job. -func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreated bool, workflowRunRepoSafety string, lockFilename string) (*Job, error) { +// preActivationCanBeSkipped indicates whether the pre_activation job can be skipped via its "if" condition. +// When true, the activation job must use always() && !cancelled() patterns to handle skipped pre_activation. +func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreated bool, preActivationCanBeSkipped bool, workflowRunRepoSafety string, lockFilename string) (*Job, error) { outputs := map[string]string{} var steps []string @@ -559,42 +570,72 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate customJobsBeforeActivation := c.getCustomJobsDependingOnPreActivation(data.Jobs) if preActivationJobCreated { - // Activation job depends on pre-activation job and checks the "activated" output + // Activation job depends on pre-activation job and checks the "success" output activationNeeds = []string{string(constants.PreActivationJobName)} // Also depend on custom jobs that run after pre_activation but before activation activationNeeds = append(activationNeeds, customJobsBeforeActivation...) - // Build activation condition: - // - If pre_activation was skipped (safe event like schedule/merge_group), proceed - // - Otherwise, check that pre_activation.outputs.activated == 'true' - preActivationSkipped := BuildEquals( - BuildPropertyAccess(fmt.Sprintf("needs.%s.result", string(constants.PreActivationJobName))), - BuildStringLiteral("skipped"), - ) - preActivationActivated := BuildEquals( - BuildPropertyAccess(fmt.Sprintf("needs.%s.outputs.%s", string(constants.PreActivationJobName), constants.ActivatedOutput)), - BuildStringLiteral("true"), - ) - // (pre_activation was skipped) OR (pre_activation.outputs.activated == 'true') - activatedExpr := BuildOr(preActivationSkipped, preActivationActivated) - - // If there are custom jobs before activation and the if condition references them, - // include that condition in the activation job's if clause - if data.If != "" && c.referencesCustomJobOutputs(data.If, data.Jobs) && len(customJobsBeforeActivation) > 0 { - // Include the custom job output condition in the activation job - unwrappedIf := stripExpressionWrapper(data.If) - ifExpr := &ExpressionNode{Expression: unwrappedIf} - combinedExpr := BuildAnd(activatedExpr, ifExpr) - activationCondition = combinedExpr.Render() - } else if data.If != "" && !c.referencesCustomJobOutputs(data.If, data.Jobs) { - // Include user's if condition that doesn't reference custom jobs - unwrappedIf := stripExpressionWrapper(data.If) - ifExpr := &ExpressionNode{Expression: unwrappedIf} - combinedExpr := BuildAnd(activatedExpr, ifExpr) - activationCondition = combinedExpr.Render() + if preActivationCanBeSkipped { + // When pre_activation CAN be skipped (via its "if" condition), we need to handle two cases: + // 1. pre_activation was skipped (safe event like schedule/merge_group) - proceed + // 2. pre_activation ran and succeeded (outputs.activated == 'true') - proceed + // We use always() && !cancelled() to ensure activation runs even when pre_activation is skipped + preActivationSkipped := BuildEquals( + BuildPropertyAccess(fmt.Sprintf("needs.%s.result", string(constants.PreActivationJobName))), + BuildStringLiteral("skipped"), + ) + preActivationSuccess := BuildEquals( + BuildPropertyAccess(fmt.Sprintf("needs.%s.outputs.%s", string(constants.PreActivationJobName), constants.ActivatedOutput)), + BuildStringLiteral("true"), + ) + // (pre_activation was skipped) OR (pre_activation.outputs.activated == 'true') + successExpr := BuildOr(preActivationSkipped, preActivationSuccess) + + // Wrap with always() && !cancelled() && to ensure downstream jobs run when pre_activation is skipped + alwaysNotCancelledExpr := BuildAlwaysNotCancelledAnd(successExpr) + + // If there are custom jobs before activation and the if condition references them, + // include that condition in the activation job's if clause + if data.If != "" && c.referencesCustomJobOutputs(data.If, data.Jobs) && len(customJobsBeforeActivation) > 0 { + // Include the custom job output condition in the activation job + unwrappedIf := stripExpressionWrapper(data.If) + ifExpr := &ExpressionNode{Expression: unwrappedIf} + combinedExpr := BuildAnd(alwaysNotCancelledExpr, ifExpr) + activationCondition = combinedExpr.Render() + } else if data.If != "" && !c.referencesCustomJobOutputs(data.If, data.Jobs) { + // Include user's if condition that doesn't reference custom jobs + unwrappedIf := stripExpressionWrapper(data.If) + ifExpr := &ExpressionNode{Expression: unwrappedIf} + combinedExpr := BuildAnd(alwaysNotCancelledExpr, ifExpr) + activationCondition = combinedExpr.Render() + } else { + activationCondition = alwaysNotCancelledExpr.Render() + } } else { - activationCondition = activatedExpr.Render() + // When pre_activation CANNOT be skipped, use the original pattern that handles both cases: + // 1. pre_activation was skipped - proceed (shouldn't happen but maintain compatibility) + // 2. pre_activation ran and succeeded (outputs.activated == 'true') - proceed + preActivationSkipped := BuildEquals( + BuildPropertyAccess(fmt.Sprintf("needs.%s.result", string(constants.PreActivationJobName))), + BuildStringLiteral("skipped"), + ) + preActivationSuccess := BuildEquals( + BuildPropertyAccess(fmt.Sprintf("needs.%s.outputs.%s", string(constants.PreActivationJobName), constants.ActivatedOutput)), + BuildStringLiteral("true"), + ) + // (pre_activation was skipped) OR (pre_activation.outputs.activated == 'true') + successExpr := BuildOr(preActivationSkipped, preActivationSuccess) + + // Include user's if condition if present + if data.If != "" { + unwrappedIf := stripExpressionWrapper(data.If) + ifExpr := &ExpressionNode{Expression: unwrappedIf} + combinedExpr := BuildAnd(successExpr, ifExpr) + activationCondition = combinedExpr.Render() + } else { + activationCondition = successExpr.Render() + } } } else { // No pre-activation check needed @@ -644,6 +685,13 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate environment = fmt.Sprintf("environment: %s", cleanManualApproval) } + // Add activated output only when pre_activation can be skipped + // This output is used by downstream jobs with the always() && !cancelled() pattern + // When pre_activation cannot be skipped, downstream jobs just check activation.outputs.activated directly + if preActivationCanBeSkipped { + outputs[constants.ActivatedOutput] = "${{ 'true' }}" + } + job := &Job{ Name: string(constants.ActivationJobName), If: activationCondition, @@ -661,7 +709,9 @@ func (c *Compiler) buildActivationJob(data *WorkflowData, preActivationJobCreate // buildMainJob creates the main agent job that runs the AI agent with the configured engine and tools. // This job depends on the activation job if it exists, and handles the main workflow logic. -func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool) (*Job, error) { +// preActivationCanBeSkipped indicates whether the pre_activation job can be skipped via its "if" condition. +// When true, downstream jobs must use always() && !cancelled() patterns. +func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool, preActivationCanBeSkipped bool) (*Job, error) { log.Printf("Building main job for workflow: %s", data.Name) var steps []string @@ -677,17 +727,56 @@ func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool) ( // Find custom jobs that depend on pre_activation - these are handled by the activation job customJobsBeforeActivation := c.getCustomJobsDependingOnPreActivation(data.Jobs) - var jobCondition = data.If + var jobCondition string if activationJobCreated { - // If the if condition references custom jobs that run before activation, - // the activation job handles the condition, so clear it here - if c.referencesCustomJobOutputs(data.If, data.Jobs) && len(customJobsBeforeActivation) > 0 { - jobCondition = "" // Activation job handles this condition - } else if !c.referencesCustomJobOutputs(data.If, data.Jobs) { - jobCondition = "" // Main job depends on activation job, so no need for inline condition + if preActivationCanBeSkipped { + // When pre_activation CAN be skipped, agent job uses the always() && !cancelled() pattern + // to handle cases where upstream jobs might be skipped but still represent successful completion. + // The condition checks that activation job succeeded via its activated output. + activationSuccessCheck := BuildEquals( + BuildPropertyAccess(fmt.Sprintf("needs.%s.outputs.%s", string(constants.ActivationJobName), constants.ActivatedOutput)), + BuildStringLiteral("true"), + ) + + // Wrap with always() && !cancelled() && to handle skipped dependencies properly + agentCondition := BuildAlwaysNotCancelledAnd(activationSuccessCheck) + + // If the if condition references custom jobs that run before activation, + // the activation job handles the condition, but we still need the base condition + if c.referencesCustomJobOutputs(data.If, data.Jobs) && len(customJobsBeforeActivation) > 0 { + // Activation job handles custom job conditions, agent just needs success check + jobCondition = agentCondition.Render() + } else if !c.referencesCustomJobOutputs(data.If, data.Jobs) && data.If != "" { + // Include user's if condition that doesn't reference custom jobs + unwrappedIf := stripExpressionWrapper(data.If) + ifExpr := &ExpressionNode{Expression: unwrappedIf} + combinedExpr := BuildAnd(agentCondition, ifExpr) + jobCondition = combinedExpr.Render() + } else { + // No extra conditions, just the always() && !cancelled() && activated pattern + jobCondition = agentCondition.Render() + } + // Note: If data.If references custom jobs that DON'T depend on pre_activation, + // we need to include them in the condition + if c.referencesCustomJobOutputs(data.If, data.Jobs) && len(customJobsBeforeActivation) == 0 { + // Custom jobs that don't depend on pre_activation, add their condition + unwrappedIf := stripExpressionWrapper(data.If) + ifExpr := &ExpressionNode{Expression: unwrappedIf} + combinedExpr := BuildAnd(&ExpressionNode{Expression: jobCondition}, ifExpr) + jobCondition = combinedExpr.Render() + } + } else { + // When pre_activation CANNOT be skipped, no "if" condition is needed on the agent job + // The agent job implicitly depends on activation succeeding through the "needs" dependency + // Include user's if condition if present (but not ones referencing custom jobs) + if data.If != "" && !c.referencesCustomJobOutputs(data.If, data.Jobs) { + jobCondition = data.If + } + // If data.If references custom jobs, don't add it here - it's handled by activation job } - // Note: If data.If references custom jobs that DON'T depend on pre_activation, - // we keep the condition on the agent job + } else { + // No activation job, use the original condition if any + jobCondition = data.If } // Note: workflow_run repository safety check is applied exclusively to activation job @@ -769,6 +858,12 @@ func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool) ( "secret_verification_result": "${{ steps.validate-secret.outputs.verification_result }}", } + // Add activated output only when pre_activation can be skipped + // This output is used by downstream jobs with the always() && !cancelled() pattern + if preActivationCanBeSkipped { + outputs[constants.ActivatedOutput] = "${{ 'true' }}" + } + // Add safe-output specific outputs if the workflow uses the safe-outputs feature if data.SafeOutputs != nil { outputs["output"] = "${{ steps.collect_output.outputs.output }}" diff --git a/pkg/workflow/compiler_activation_jobs_test.go b/pkg/workflow/compiler_activation_jobs_test.go index 308e13c5aa..e289e7ad66 100644 --- a/pkg/workflow/compiler_activation_jobs_test.go +++ b/pkg/workflow/compiler_activation_jobs_test.go @@ -23,7 +23,7 @@ func TestBuildPreActivationJob_WithPermissionCheck(t *testing.T) { }, } - job, err := compiler.buildPreActivationJob(workflowData, true) + job, _, err := compiler.buildPreActivationJob(workflowData, true, false) require.NoError(t, err, "buildPreActivationJob should succeed with permission check") require.NotNil(t, job) @@ -31,7 +31,7 @@ func TestBuildPreActivationJob_WithPermissionCheck(t *testing.T) { assert.NotNil(t, job.Outputs, "Job should have outputs") // Check for activated output - _, hasActivated := job.Outputs["activated"] + _, hasActivated := job.Outputs[constants.ActivatedOutput] assert.True(t, hasActivated, "Job should have 'activated' output") // Check that steps contain membership check @@ -49,7 +49,7 @@ func TestBuildPreActivationJob_WithoutPermissionCheck(t *testing.T) { Command: []string{"test"}, } - job, err := compiler.buildPreActivationJob(workflowData, false) + job, _, err := compiler.buildPreActivationJob(workflowData, false, false) require.NoError(t, err, "buildPreActivationJob should succeed without permission check") require.NotNil(t, job) @@ -69,7 +69,7 @@ func TestBuildPreActivationJob_WithStopTime(t *testing.T) { StopTime: "2024-12-31T23:59:59Z", } - job, err := compiler.buildPreActivationJob(workflowData, false) + job, _, err := compiler.buildPreActivationJob(workflowData, false, false) require.NoError(t, err, "buildPreActivationJob should succeed with stop-time") require.NotNil(t, job) @@ -122,7 +122,7 @@ func TestBuildPreActivationJob_WithReaction(t *testing.T) { AIReaction: tt.reaction, } - job, err := compiler.buildPreActivationJob(workflowData, false) + job, _, err := compiler.buildPreActivationJob(workflowData, false, false) require.NoError(t, err) require.NotNil(t, job) @@ -171,7 +171,7 @@ func TestBuildPreActivationJob_WithCustomStepsAndOutputs(t *testing.T) { }, } - job, err := compiler.buildPreActivationJob(workflowData, false) + job, _, err := compiler.buildPreActivationJob(workflowData, false, false) require.NoError(t, err, "buildPreActivationJob should succeed with custom fields") require.NotNil(t, job) @@ -194,7 +194,7 @@ func TestBuildActivationJob_Basic(t *testing.T) { MarkdownContent: "# Test\n\nContent", } - job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + job, err := compiler.buildActivationJob(workflowData, false, false, "", "test.lock.yml") require.NoError(t, err, "buildActivationJob should succeed") require.NotNil(t, job) @@ -212,7 +212,7 @@ func TestBuildActivationJob_WithPreActivation(t *testing.T) { MarkdownContent: "# Test\n\nContent", } - job, err := compiler.buildActivationJob(workflowData, true, "", "test.lock.yml") + job, err := compiler.buildActivationJob(workflowData, true, true, "", "test.lock.yml") require.NoError(t, err, "buildActivationJob should succeed with pre-activation") require.NotNil(t, job) @@ -232,7 +232,7 @@ func TestBuildActivationJob_WithReaction(t *testing.T) { AIReaction: "rocket", } - job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + job, err := compiler.buildActivationJob(workflowData, false, false, "", "test.lock.yml") require.NoError(t, err) require.NotNil(t, job) @@ -253,7 +253,7 @@ func TestBuildMainJob_Basic(t *testing.T) { AI: "copilot", } - job, err := compiler.buildMainJob(workflowData, false) + job, err := compiler.buildMainJob(workflowData, false, false) require.NoError(t, err, "buildMainJob should succeed") require.NotNil(t, job) @@ -272,7 +272,7 @@ func TestBuildMainJob_WithActivation(t *testing.T) { AI: "copilot", } - job, err := compiler.buildMainJob(workflowData, true) + job, err := compiler.buildMainJob(workflowData, true, true) require.NoError(t, err, "buildMainJob should succeed with activation") require.NotNil(t, job) @@ -293,7 +293,7 @@ func TestBuildMainJob_WithPermissions(t *testing.T) { Permissions: "contents: read\nissues: write", } - job, err := compiler.buildMainJob(workflowData, false) + job, err := compiler.buildMainJob(workflowData, false, false) require.NoError(t, err) require.NotNil(t, job) @@ -383,7 +383,7 @@ func TestBuildPreActivationJob_Integration(t *testing.T) { }, } - job, err := compiler.buildPreActivationJob(workflowData, true) + job, _, err := compiler.buildPreActivationJob(workflowData, true, false) require.NoError(t, err, "buildPreActivationJob should succeed with all features") require.NotNil(t, job) @@ -399,8 +399,8 @@ func TestBuildPreActivationJob_Integration(t *testing.T) { assert.Contains(t, job.Permissions, "issues: write", "Should have issues write permission") assert.Contains(t, job.Permissions, "pull-requests: write", "Should have PR write permission") - // Should have activated output - _, hasActivated := job.Outputs["activated"] + // Should have activated output (pre_activation always has it) + _, hasActivated := job.Outputs[constants.ActivatedOutput] assert.True(t, hasActivated, "Should have activated output") } @@ -415,7 +415,7 @@ func TestBuildActivationJob_WithWorkflowRunRepoSafety(t *testing.T) { } // Test with workflow_run repo safety enabled - job, err := compiler.buildActivationJob(workflowData, false, "workflow_run", "test.lock.yml") + job, err := compiler.buildActivationJob(workflowData, false, false, "workflow_run", "test.lock.yml") require.NoError(t, err) require.NotNil(t, job) @@ -455,7 +455,7 @@ func TestBuildMainJob_EngineSpecific(t *testing.T) { AI: tt.engine, } - job, err := compiler.buildMainJob(workflowData, false) + job, err := compiler.buildMainJob(workflowData, false, false) require.NoError(t, err, "buildMainJob should succeed for engine %s", tt.engine) require.NotNil(t, job) assert.NotEmpty(t, job.Steps, "Should have steps for engine %s", tt.engine) diff --git a/pkg/workflow/compiler_jobs.go b/pkg/workflow/compiler_jobs.go index c0a2b07856..ef26857b27 100644 --- a/pkg/workflow/compiler_jobs.go +++ b/pkg/workflow/compiler_jobs.go @@ -53,6 +53,24 @@ func (c *Compiler) referencesCustomJobOutputs(condition string, customJobs map[s return false } +// hasRealCustomJobs checks if there are custom jobs other than pre-activation/pre_activation. +// Custom jobs make the skip-pre-activation optimization too complex, so we disable it +// when any real custom jobs are present. +func (c *Compiler) hasRealCustomJobs(customJobs map[string]any) bool { + if customJobs == nil { + return false + } + for jobName := range customJobs { + // Skip pre-activation variants - these are handled specially + if jobName == string(constants.PreActivationJobName) || jobName == "pre-activation" { + continue + } + // Any other job is a "real" custom job + return true + } + return false +} + // jobDependsOnPreActivation checks if a job config has pre_activation as a dependency. func jobDependsOnPreActivation(jobConfig map[string]any) bool { if needs, hasNeeds := jobConfig["needs"]; hasNeeds { @@ -159,27 +177,30 @@ func (c *Compiler) buildJobs(data *WorkflowData, markdownPath string) error { // Build pre-activation job if needed (combines membership checks, stop-time validation, skip-if-match check, skip-if-no-match check, and command position check) var preActivationJobCreated bool + var preActivationCanBeSkipped bool hasCommandTrigger := len(data.Command) > 0 + hasRealCustomJobs := c.hasRealCustomJobs(data.Jobs) if needsPermissionCheck || hasStopTime || hasSkipIfMatch || hasSkipIfNoMatch || hasCommandTrigger { compilerJobsLog.Print("Building pre-activation job") - preActivationJob, err := c.buildPreActivationJob(data, needsPermissionCheck) + preActivationJob, canBeSkipped, err := c.buildPreActivationJob(data, needsPermissionCheck, hasRealCustomJobs) if err != nil { return fmt.Errorf("failed to build %s job: %w", constants.PreActivationJobName, err) } if err := c.jobManager.AddJob(preActivationJob); err != nil { return fmt.Errorf("failed to add %s job: %w", constants.PreActivationJobName, err) } - compilerJobsLog.Printf("Successfully added pre-activation job: %s", constants.PreActivationJobName) + compilerJobsLog.Printf("Successfully added pre-activation job: %s (canBeSkipped=%v)", constants.PreActivationJobName, canBeSkipped) preActivationJobCreated = true + preActivationCanBeSkipped = canBeSkipped } // Build activation job if needed (preamble job that handles runtime conditions) - // If pre-activation job exists, activation job depends on it and checks the "activated" output + // If pre-activation job exists, activation job depends on it and checks the "success" output var activationJobCreated bool if c.isActivationJobNeeded() { compilerJobsLog.Print("Building activation job") - activationJob, err := c.buildActivationJob(data, preActivationJobCreated, workflowRunRepoSafety, lockFilename) + activationJob, err := c.buildActivationJob(data, preActivationJobCreated, preActivationCanBeSkipped, workflowRunRepoSafety, lockFilename) if err != nil { return fmt.Errorf("failed to build activation job: %w", err) } @@ -192,7 +213,7 @@ func (c *Compiler) buildJobs(data *WorkflowData, markdownPath string) error { // Build main workflow job compilerJobsLog.Print("Building main job") - mainJob, err := c.buildMainJob(data, activationJobCreated) + mainJob, err := c.buildMainJob(data, activationJobCreated, preActivationCanBeSkipped) if err != nil { return fmt.Errorf("failed to build main job: %w", err) } @@ -210,7 +231,7 @@ func (c *Compiler) buildJobs(data *WorkflowData, markdownPath string) error { if len(data.Jobs) > 0 { compilerJobsLog.Printf("Building %d custom jobs from frontmatter", len(data.Jobs)) } - if err := c.buildCustomJobs(data, activationJobCreated); err != nil { + if err := c.buildCustomJobs(data, activationJobCreated, preActivationCanBeSkipped); err != nil { return fmt.Errorf("failed to build custom jobs: %w", err) } @@ -292,8 +313,10 @@ func (c *Compiler) extractJobsFromFrontmatter(frontmatter map[string]any) map[st } // buildCustomJobs creates custom jobs defined in the frontmatter jobs section -func (c *Compiler) buildCustomJobs(data *WorkflowData, activationJobCreated bool) error { - compilerJobsLog.Printf("Building %d custom jobs", len(data.Jobs)) +// preActivationCanBeSkipped indicates whether the pre_activation job can be skipped via its "if" condition. +// When false (custom jobs present), we don't need always() && !cancelled() patterns. +func (c *Compiler) buildCustomJobs(data *WorkflowData, activationJobCreated bool, preActivationCanBeSkipped bool) error { + compilerJobsLog.Printf("Building %d custom jobs (preActivationCanBeSkipped=%v)", len(data.Jobs), preActivationCanBeSkipped) for jobName, jobConfig := range data.Jobs { // Skip jobs.pre-activation (or pre_activation) as it's handled specially in buildPreActivationJob if jobName == string(constants.PreActivationJobName) || jobName == "pre-activation" { @@ -336,10 +359,46 @@ func (c *Compiler) buildCustomJobs(data *WorkflowData, activationJobCreated bool } } + // Extract user-specified if condition + var userIfCondition string if ifCond, hasIf := configMap["if"]; hasIf { if ifStr, ok := ifCond.(string); ok { - job.If = c.extractExpressionFromIfString(ifStr) + userIfCondition = c.extractExpressionFromIfString(ifStr) + } + } + + // If the job depends on activation (either explicitly or implicitly added above), + // we may need to add an "if" condition. The pattern depends on whether pre_activation can be skipped: + // - If preActivationCanBeSkipped: use always() && !cancelled() pattern to handle skipped jobs + // - Otherwise: no automatic "if" condition needed (GitHub Actions handles dependency failures) + dependsOnActivation := false + for _, need := range job.Needs { + if need == string(constants.ActivationJobName) { + dependsOnActivation = true + break + } + } + + if dependsOnActivation && activationJobCreated && preActivationCanBeSkipped { + // When pre_activation can be skipped, use always() && !cancelled() pattern + activationSuccessCheck := BuildEquals( + BuildPropertyAccess(fmt.Sprintf("needs.%s.outputs.%s", string(constants.ActivationJobName), constants.ActivatedOutput)), + BuildStringLiteral("true"), + ) + baseCondition := BuildAlwaysNotCancelledAnd(activationSuccessCheck) + + if userIfCondition != "" { + // Combine with user's condition: always() && !cancelled() && activated && (user_condition) + userExpr := &ExpressionNode{Expression: userIfCondition} + combinedExpr := BuildAnd(baseCondition, userExpr) + job.If = combinedExpr.Render() + } else { + job.If = baseCondition.Render() } + compilerJobsLog.Printf("Added always() && !cancelled() && activated condition to custom job '%s'", jobName) + } else if userIfCondition != "" { + // No activation dependency or pre_activation cannot be skipped, just use the user's condition + job.If = userIfCondition } // Extract permissions diff --git a/pkg/workflow/compiler_jobs_test.go b/pkg/workflow/compiler_jobs_test.go index 7cf29bb518..abac720375 100644 --- a/pkg/workflow/compiler_jobs_test.go +++ b/pkg/workflow/compiler_jobs_test.go @@ -82,7 +82,7 @@ func TestBuildPreActivationJobWithPermissionCheck(t *testing.T) { }, } - job, err := compiler.buildPreActivationJob(workflowData, true) + job, _, err := compiler.buildPreActivationJob(workflowData, true, false) if err != nil { t.Fatalf("buildPreActivationJob() returned error: %v", err) } @@ -97,7 +97,7 @@ func TestBuildPreActivationJobWithPermissionCheck(t *testing.T) { } // Check for activated output - if _, ok := job.Outputs["activated"]; !ok { + if _, ok := job.Outputs[constants.ActivatedOutput]; !ok { t.Error("Expected 'activated' output") } @@ -117,7 +117,7 @@ func TestBuildPreActivationJobWithStopTime(t *testing.T) { SafeOutputs: &SafeOutputsConfig{}, } - job, err := compiler.buildPreActivationJob(workflowData, false) + job, _, err := compiler.buildPreActivationJob(workflowData, false, false) if err != nil { t.Fatalf("buildPreActivationJob() returned error: %v", err) } @@ -138,7 +138,7 @@ func TestBuildActivationJob(t *testing.T) { SafeOutputs: &SafeOutputsConfig{}, } - job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + job, err := compiler.buildActivationJob(workflowData, false, false, "", "test.lock.yml") if err != nil { t.Fatalf("buildActivationJob() returned error: %v", err) } @@ -164,7 +164,7 @@ func TestBuildActivationJobWithReaction(t *testing.T) { SafeOutputs: &SafeOutputsConfig{}, } - job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + job, err := compiler.buildActivationJob(workflowData, false, false, "", "test.lock.yml") if err != nil { t.Fatalf("buildActivationJob() returned error: %v", err) } @@ -192,7 +192,7 @@ func TestBuildActivationJobCampaignOrchestratorFilename(t *testing.T) { } // Test with campaign orchestrator filename (with .g.) - job, err := compiler.buildActivationJob(workflowData, false, "", "example.campaign.lock.yml") + job, err := compiler.buildActivationJob(workflowData, false, false, "", "example.campaign.lock.yml") if err != nil { t.Fatalf("buildActivationJob() returned error: %v", err) } @@ -221,7 +221,7 @@ func TestBuildMainJobWithActivation(t *testing.T) { Permissions: "permissions:\n contents: read", } - job, err := compiler.buildMainJob(workflowData, true) + job, err := compiler.buildMainJob(workflowData, true, true) if err != nil { t.Fatalf("buildMainJob() returned error: %v", err) } diff --git a/pkg/workflow/data/action_pins.json b/pkg/workflow/data/action_pins.json index edbd2e8785..2db5179bb9 100644 --- a/pkg/workflow/data/action_pins.json +++ b/pkg/workflow/data/action_pins.json @@ -25,11 +25,6 @@ "version": "v4.3.0", "sha": "0057852bfaa89a56745cba8c7296529d2fc39830" }, - "actions/checkout@v3": { - "repo": "actions/checkout", - "version": "v3", - "sha": "f43a0e5ff2bd294095638e18286ca9a3d1956744" - }, "actions/checkout@v4": { "repo": "actions/checkout", "version": "v4", diff --git a/pkg/workflow/expression_builder.go b/pkg/workflow/expression_builder.go index 74dfa497e3..bfe94c7d06 100644 --- a/pkg/workflow/expression_builder.go +++ b/pkg/workflow/expression_builder.go @@ -61,6 +61,21 @@ func BuildAnd(left ConditionNode, right ConditionNode) ConditionNode { return &AndNode{Left: left, Right: right} } +// BuildAlwaysNotCancelledAnd creates a condition with "always() && !cancelled() && (inner)" pattern. +// This pattern ensures that jobs run even when upstream dependencies are skipped, +// while still being cancelled if the workflow itself is cancelled. +// This is critical for the activation and downstream jobs to run when pre_activation is skipped. +func BuildAlwaysNotCancelledAnd(inner ConditionNode) ConditionNode { + alwaysFunc := BuildFunctionCall("always") + notCancelledFunc := &NotNode{ + Child: BuildFunctionCall("cancelled"), + } + // always() && !cancelled() + alwaysNotCancelled := &AndNode{Left: alwaysFunc, Right: notCancelledFunc} + // always() && !cancelled() && (inner) + return &AndNode{Left: alwaysNotCancelled, Right: inner} +} + // BuildReactionCondition creates a condition tree for the add_reaction job func BuildReactionCondition() ConditionNode { expressionBuilderLog.Print("Building reaction condition for multiple event types") @@ -169,25 +184,18 @@ func BuildNotFromFork() *ComparisonNode { } func BuildSafeOutputType(outputType string) ConditionNode { - // Use !cancelled() && needs.agent.result != 'skipped' to properly handle workflow cancellation - // !cancelled() allows jobs to run when dependencies fail (for error reporting) - // needs.agent.result != 'skipped' prevents running when workflow is cancelled (dependencies get skipped) - notCancelledFunc := &NotNode{ - Child: BuildFunctionCall("cancelled"), - } - - // Check that agent job was not skipped (happens when workflow is cancelled) - agentNotSkipped := &ComparisonNode{ - Left: BuildPropertyAccess(fmt.Sprintf("needs.%s.result", constants.AgentJobName)), - Operator: "!=", - Right: BuildStringLiteral("skipped"), - } + // Use always() && !cancelled() && needs.agent.outputs.activated == 'true' pattern + // to properly handle workflow cancellation and upstream job skipping. + // always() ensures this job runs even if upstream jobs were skipped (but completed successfully) + // !cancelled() prevents running when the workflow itself is cancelled + // needs.agent.outputs.activated == 'true' ensures the agent job completed successfully + agentSuccess := BuildEquals( + BuildPropertyAccess(fmt.Sprintf("needs.%s.outputs.%s", constants.AgentJobName, constants.ActivatedOutput)), + BuildStringLiteral("true"), + ) - // Combine !cancelled() with agent not skipped check - baseCondition := &AndNode{ - Left: notCancelledFunc, - Right: agentNotSkipped, - } + // Wrap with always() && !cancelled() && to handle skipped dependencies properly + baseCondition := BuildAlwaysNotCancelledAnd(agentSuccess) // Always check that the output type is present in agent outputs // This prevents the job from running when the agent didn't produce any outputs of this type diff --git a/pkg/workflow/expressions_cancelled_test.go b/pkg/workflow/expressions_cancelled_test.go index 5fd6297c21..129e7ac910 100644 --- a/pkg/workflow/expressions_cancelled_test.go +++ b/pkg/workflow/expressions_cancelled_test.go @@ -5,19 +5,22 @@ package workflow import ( "strings" "testing" + + "github.com/githubnext/gh-aw/pkg/constants" ) // TestBuildSafeOutputTypeWithCancelled verifies that BuildSafeOutputType properly handles workflow cancellation. // // Background: -// - always() runs even when the workflow is cancelled (incorrect behavior) -// - !cancelled() alone is insufficient (returns true when dependencies are skipped during cancellation) -// - !cancelled() && needs.agent.result != 'skipped' is correct (prevents running when workflow is cancelled) +// - always() ensures jobs run even when upstream dependencies are skipped (but completed successfully) +// - !cancelled() prevents running when the workflow itself is cancelled +// - needs.agent.outputs.activated == 'true' ensures the agent job completed successfully // +// The combined pattern: always() && !cancelled() && needs.agent.outputs.activated == 'true' // This test ensures safe-output jobs: // 1. Run when dependencies succeed -// 2. Run when dependencies fail (for error reporting) -// 3. Skip when the workflow is cancelled (dependencies get skipped, not cancelled) +// 2. Run when dependencies are skipped (but successful) +// 3. Skip when the workflow is cancelled func TestBuildSafeOutputTypeWithCancelled(t *testing.T) { tests := []struct { name string @@ -26,27 +29,29 @@ func TestBuildSafeOutputTypeWithCancelled(t *testing.T) { unexpectedContains []string }{ { - name: "create_issue should use !cancelled() and agent not skipped with contains check", + name: "create_issue should use always() && !cancelled() && activated pattern", outputType: "create_issue", expectedContains: []string{ + "always()", "!cancelled()", - "needs.agent.result != 'skipped'", + "needs." + string(constants.AgentJobName) + ".outputs." + constants.ActivatedOutput + " == 'true'", "contains(needs.agent.outputs.output_types, 'create_issue')", }, unexpectedContains: []string{ - "always()", + "needs.agent.result != 'skipped'", }, }, { - name: "push-to-pull-request-branch should use !cancelled() and agent not skipped", + name: "push-to-pull-request-branch should use always() && !cancelled() && activated pattern", outputType: "push_to_pull_request_branch", expectedContains: []string{ + "always()", "!cancelled()", - "needs.agent.result != 'skipped'", + "needs." + string(constants.AgentJobName) + ".outputs." + constants.ActivatedOutput + " == 'true'", "contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch')", }, unexpectedContains: []string{ - "always()", + "needs.agent.result != 'skipped'", }, }, } diff --git a/pkg/workflow/jobs_test.go b/pkg/workflow/jobs_test.go index c89bcd2524..58556f31fb 100644 --- a/pkg/workflow/jobs_test.go +++ b/pkg/workflow/jobs_test.go @@ -597,7 +597,7 @@ func TestBuildCustomJobsActivationDependency(t *testing.T) { Jobs: tt.jobs, } - err := c.buildCustomJobs(data, tt.activationJobCreated) + err := c.buildCustomJobs(data, tt.activationJobCreated, false) if err != nil { t.Fatalf("%s: buildCustomJobs() error = %v", tt.description, err) } diff --git a/pkg/workflow/main_job_env_test.go b/pkg/workflow/main_job_env_test.go index e451111a41..ccc0c74aae 100644 --- a/pkg/workflow/main_job_env_test.go +++ b/pkg/workflow/main_job_env_test.go @@ -76,7 +76,7 @@ func TestMainJobEnvironmentVariables(t *testing.T) { data.SafeOutputs = compiler.extractSafeOutputsConfig(tt.frontmatter) // Build the main job - job, err := compiler.buildMainJob(data, false) + job, err := compiler.buildMainJob(data, false, false) if err != nil { t.Fatalf("Failed to build main job: %v", err) } diff --git a/pkg/workflow/notify_comment_test.go b/pkg/workflow/notify_comment_test.go index b461d90287..8aee6d2cd2 100644 --- a/pkg/workflow/notify_comment_test.go +++ b/pkg/workflow/notify_comment_test.go @@ -419,7 +419,7 @@ func TestActivationJobWithMessages(t *testing.T) { } // Build the activation job - job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + job, err := compiler.buildActivationJob(workflowData, false, false, "", "test.lock.yml") if err != nil { t.Fatalf("Failed to build activation job: %v", err) } @@ -463,7 +463,7 @@ func TestActivationJobWithoutMessages(t *testing.T) { } // Build the activation job - job, err := compiler.buildActivationJob(workflowData, false, "", "test.lock.yml") + job, err := compiler.buildActivationJob(workflowData, false, false, "", "test.lock.yml") if err != nil { t.Fatalf("Failed to build activation job: %v", err) } diff --git a/pkg/workflow/pre_activation_custom_fields_test.go b/pkg/workflow/pre_activation_custom_fields_test.go index 254c7d61a9..6ebaa2c628 100644 --- a/pkg/workflow/pre_activation_custom_fields_test.go +++ b/pkg/workflow/pre_activation_custom_fields_test.go @@ -110,9 +110,9 @@ Test workflow with custom pre-activation outputs t.Error("Expected custom output 'custom_output' to be present in pre_activation job") } - // Verify the activated output is still present - if !strings.Contains(lockContentStr, "activated:") { - t.Error("Expected standard 'activated' output to still be present") + // Verify the success output is still present + if !strings.Contains(lockContentStr, "success:") { + t.Error("Expected standard 'success' output to still be present") } }) @@ -311,9 +311,9 @@ Test that both pre-activation and pre_activation are imported t.Error("Expected 'underscore_status' output to be present") } - // Verify the activated output is still present - if !strings.Contains(lockContentStr, "activated:") { - t.Error("Expected standard 'activated' output to still be present") + // Verify the success output is still present + if !strings.Contains(lockContentStr, "success:") { + t.Error("Expected standard 'success' output to still be present") } }) } diff --git a/pkg/workflow/pre_activation_skip_test.go b/pkg/workflow/pre_activation_skip_test.go index a0640efea9..b24e5e4298 100644 --- a/pkg/workflow/pre_activation_skip_test.go +++ b/pkg/workflow/pre_activation_skip_test.go @@ -94,10 +94,14 @@ This workflow runs on schedule and when issues are opened. // Verify activation job handles skipped pre_activation activationSection := extractJobSectionForSkipTest(lockContentStr, string(constants.ActivationJobName)) require.NotEmpty(t, activationSection, "Should have activation job") + assert.Contains(t, activationSection, "always()", + "activation should use always() to run even when pre_activation is skipped") + assert.Contains(t, activationSection, "!cancelled()", + "activation should check !cancelled() to respect workflow cancellation") assert.Contains(t, activationSection, "needs.pre_activation.result == 'skipped'", "activation should check if pre_activation was skipped") - assert.Contains(t, activationSection, "needs.pre_activation.outputs.activated == 'true'", - "activation should also check activated output for non-safe events") + assert.Contains(t, activationSection, "needs.pre_activation.outputs.success == 'true'", + "activation should also check success output for non-safe events") }) t.Run("issue_workflow_does_not_skip_pre_activation", func(t *testing.T) { diff --git a/pkg/workflow/safe_jobs_test.go b/pkg/workflow/safe_jobs_test.go index 8a9793dd54..84f3e99f6f 100644 --- a/pkg/workflow/safe_jobs_test.go +++ b/pkg/workflow/safe_jobs_test.go @@ -227,8 +227,8 @@ func TestBuildSafeJobs(t *testing.T) { t.Errorf("Expected needs %v, got %v", expectedNeeds, job.Needs) } - // Check if condition - should now combine safe output type check with user condition - expectedIf := "(((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'deploy'))) && (github.event.issue.number)" + // Check if condition - should use always() && !cancelled() && activated pattern with user condition + expectedIf := "((((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'deploy'))) && (github.event.issue.number)" if job.If != expectedIf { t.Errorf("Expected if condition to be '%s', got '%s'", expectedIf, job.If) } @@ -331,8 +331,8 @@ func TestBuildSafeJobsWithoutCustomIfCondition(t *testing.T) { break } - // Check if condition - should only have safe output type check (no custom condition) - expectedIf := "((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'notify'))" + // Check if condition - should use always() && !cancelled() && activated pattern + expectedIf := "(((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'notify'))" if job.If != expectedIf { t.Errorf("Expected if condition to be '%s', got '%s'", expectedIf, job.If) } @@ -379,8 +379,8 @@ func TestBuildSafeJobsWithDashesInName(t *testing.T) { t.Errorf("Expected job name to be 'send_notification', got '%s'", job.Name) } - // Check if condition - should check for underscore version in output_types - expectedIf := "((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'send_notification'))" + // Check if condition - should use always() && !cancelled() && activated pattern + expectedIf := "(((always()) && (!cancelled())) && (needs.agent.outputs.activated == 'true')) && (contains(needs.agent.outputs.output_types, 'send_notification'))" if job.If != expectedIf { t.Errorf("Expected if condition to be '%s', got '%s'", expectedIf, job.If) } diff --git a/pkg/workflow/skip_if_no_match_test.go b/pkg/workflow/skip_if_no_match_test.go index 9dceea2dc8..59cee17ec9 100644 --- a/pkg/workflow/skip_if_no_match_test.go +++ b/pkg/workflow/skip_if_no_match_test.go @@ -74,9 +74,9 @@ This workflow has a skip-if-no-match configuration. t.Error("Expected check_skip_if_no_match step ID") } - // Verify the activated output includes skip_no_match_check_ok condition + // Verify the success output includes skip_no_match_check_ok condition if !strings.Contains(lockContentStr, "steps.check_skip_if_no_match.outputs.skip_no_match_check_ok") { - t.Error("Expected activated output to include skip_no_match_check_ok condition") + t.Error("Expected success output to include skip_no_match_check_ok condition") } // Verify skip-if-no-match is commented out in the frontmatter @@ -135,11 +135,11 @@ This workflow has both stop-after and skip-if-no-match. t.Error("Expected skip-if-no-match check to be present") } - // Verify the activated output includes both conditions + // Verify the success output includes both conditions if !strings.Contains(lockContentStr, "steps.check_membership.outputs.is_team_member == 'true'") || !strings.Contains(lockContentStr, "steps.check_stop_time.outputs.stop_time_ok == 'true'") || !strings.Contains(lockContentStr, "steps.check_skip_if_no_match.outputs.skip_no_match_check_ok == 'true'") { - t.Error("Expected activated output to include all three conditions") + t.Error("Expected success output to include all three conditions") } }) @@ -183,10 +183,10 @@ This workflow has skip-if-no-match but no role restrictions. t.Error("Expected skip-if-no-match check to be present") } - // Since there's no role check, activated should only depend on skip_no_match_check_ok + // Since there's no role check, success should only depend on skip_no_match_check_ok // Note: There's still a membership check with default roles, so both will be present if !strings.Contains(lockContentStr, "steps.check_skip_if_no_match.outputs.skip_no_match_check_ok") { - t.Error("Expected activated output to include skip_no_match_check_ok condition") + t.Error("Expected success output to include skip_no_match_check_ok condition") } }) @@ -239,7 +239,7 @@ This workflow uses object format with min parameter. // Verify skip_no_match_check_ok condition is used if !strings.Contains(lockContentStr, "steps.check_skip_if_no_match.outputs.skip_no_match_check_ok") { - t.Error("Expected activated output to include skip_no_match_check_ok condition") + t.Error("Expected success output to include skip_no_match_check_ok condition") } }) @@ -332,11 +332,11 @@ This workflow uses both skip-if-match and skip-if-no-match. // Verify both output conditions are used if !strings.Contains(lockContentStr, "steps.check_skip_if_match.outputs.skip_check_ok") { - t.Error("Expected activated output to include skip_check_ok condition") + t.Error("Expected success output to include skip_check_ok condition") } if !strings.Contains(lockContentStr, "steps.check_skip_if_no_match.outputs.skip_no_match_check_ok") { - t.Error("Expected activated output to include skip_no_match_check_ok condition") + t.Error("Expected success output to include skip_no_match_check_ok condition") } }) } diff --git a/pkg/workflow/stop_time_check_job_test.go b/pkg/workflow/stop_time_check_job_test.go index cb463c5e06..1925cd9e1e 100644 --- a/pkg/workflow/stop_time_check_job_test.go +++ b/pkg/workflow/stop_time_check_job_test.go @@ -85,12 +85,12 @@ This workflow has a stop-after configuration. t.Error("Stop-time check should not be in agent job") } - // Verify pre_activation job outputs "activated" as a direct expression combining both checks + // Verify pre_activation job outputs "success" as a direct expression combining both checks // Since workflow_dispatch requires permission checks by default, AND has stop-time // The expression builder adds parentheses around each condition - expectedActivated := "activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_stop_time.outputs.stop_time_ok == 'true') }}" - if !strings.Contains(lockContentStr, expectedActivated) { - t.Error("Expected pre_activation job to have combined 'activated' output expression") + expectedSuccess := "success: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_stop_time.outputs.stop_time_ok == 'true') }}" + if !strings.Contains(lockContentStr, expectedSuccess) { + t.Error("Expected pre_activation job to have combined 'success' output expression") } // Verify old jobs don't exist @@ -194,10 +194,10 @@ This workflow requires membership checks. t.Error("Expected activation job to depend on pre_activation job") } - // Verify activation job checks activated output (with skipped fallback for safe events) - // New format: (needs.pre_activation.result == 'skipped') || (needs.pre_activation.outputs.activated == 'true') + // Verify activation job uses the standard pattern with activated output check + // Format: (needs.pre_activation.result == 'skipped') || (needs.pre_activation.outputs.activated == 'true') if !strings.Contains(activationSection, "needs.pre_activation.result == 'skipped'") { - t.Error("Expected activation job to check if pre_activation was skipped (for safe events)") + t.Error("Expected activation job to check if pre_activation was skipped") } if !strings.Contains(activationSection, "needs.pre_activation.outputs.activated == 'true'") { t.Error("Expected activation job to check pre_activation.outputs.activated") @@ -249,11 +249,11 @@ This workflow has both membership check and stop-after. t.Error("Expected stop-time check in pre_activation job") } - // Verify the activated output combines both membership and stop-time checks + // Verify the success output combines both membership and stop-time checks // The expression builder adds parentheses around each condition - expectedActivated := "activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_stop_time.outputs.stop_time_ok == 'true') }}" - if !strings.Contains(lockContentStr, expectedActivated) { - t.Error("Expected activated output to combine both membership and stop-time checks") + expectedSuccess := "success: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_stop_time.outputs.stop_time_ok == 'true') }}" + if !strings.Contains(lockContentStr, expectedSuccess) { + t.Error("Expected success output to combine both membership and stop-time checks") } // Verify the structure: membership check happens before stop-time check