diff --git a/.github/scripts/evaluate-workflow-status.js b/.github/scripts/evaluate-workflow-status.js new file mode 100644 index 00000000..70337cbd --- /dev/null +++ b/.github/scripts/evaluate-workflow-status.js @@ -0,0 +1,84 @@ +const DEFAULT_REQUIRED_BRANCH = 'main'; + +function resolveBranch(context) { + const { eventName, ref, payload } = context; + + if (eventName === 'workflow_run') { + return payload.workflow_run?.head_branch || ''; + } + + if (eventName === 'pull_request' || eventName === 'pull_request_target') { + return payload.pull_request?.head?.ref || ''; + } + + if (typeof ref === 'string' && ref.startsWith('refs/heads/')) { + return ref.replace('refs/heads/', ''); + } + + return ''; +} + +async function ensureSuccessfulRun({ github, context, core }, workflowFile, branch) { + const { data } = await github.rest.actions.listWorkflowRuns({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: workflowFile, + branch, + per_page: 1, + status: 'completed' + }); + + if (!data.workflow_runs.length) { + core.setFailed(`No completed runs of ${workflowFile} found on branch ${branch}.`); + return false; + } + + const [run] = data.workflow_runs; + + if (run.conclusion !== 'success') { + core.setFailed(`Latest ${workflowFile} run (${run.id}) concluded with ${run.conclusion}.`); + return false; + } + + core.info(`Dependency workflow ${workflowFile} succeeded on branch ${branch} (run id ${run.id}).`); + return true; +} + +async function evaluateWorkflowStatus({ github, context, core }, options) { + const { + dependencyWorkflowFile, + requiredBranch = DEFAULT_REQUIRED_BRANCH, + } = options; + const branch = resolveBranch(context); + + if (!branch) { + core.info('Unable to determine triggering branch, skipping downstream jobs.'); + core.setOutput('should-run', 'false'); + return; + } + + if (branch !== requiredBranch) { + core.info(`Branch ${branch} is not ${requiredBranch}; skipping downstream jobs.`); + core.setOutput('should-run', 'false'); + return; + } + + if (context.eventName === 'workflow_run') { + const conclusion = context.payload.workflow_run?.conclusion; + if (conclusion !== 'success') { + core.setFailed(`Upstream workflow ${context.payload.workflow_run?.name} concluded with ${conclusion}.`); + return; + } + } + + const ok = await ensureSuccessfulRun({ github, context, core }, dependencyWorkflowFile, branch); + if (!ok) { + return; + } + + core.setOutput('should-run', 'true'); +} + +module.exports = { + evaluateWorkflowStatus, +}; diff --git a/.github/workflows/iac-pipeline-create.yml b/.github/workflows/iac-pipeline-create.yml index b49d65fd..64b4093f 100644 --- a/.github/workflows/iac-pipeline-create.yml +++ b/.github/workflows/iac-pipeline-create.yml @@ -15,9 +15,41 @@ on: workflow_dispatch: branches: - main + workflow_run: + workflows: + - Alicloud Landing Zone Baseline + types: + - completed jobs: + verify-baseline-status: + name: Verify Alicloud baseline readiness + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + outputs: + should-run: ${{ steps.evaluate.outputs.should-run }} + steps: + - name: Checkout helpers + uses: actions/checkout@v4 + with: + sparse-checkout: | + .github/scripts/evaluate-workflow-status.js + sparse-checkout-cone-mode: false + - name: Evaluate upstream workflow status + id: evaluate + uses: actions/github-script@v7 + with: + script: | + const { evaluateWorkflowStatus } = require('./.github/scripts/evaluate-workflow-status'); + await evaluateWorkflowStatus({ github, context, core }, { + dependencyWorkflowFile: 'iac-pipeline-alicloud-landingzone-baseline.yaml', + }); + apply-cluster-resources: + needs: verify-baseline-status + if: needs.verify-baseline-status.outputs.should-run == 'true' uses: svc-design/actions/.github/workflows/setup-gcp-cloud.yml@main with: config: 'multi-cluster-config.yaml' diff --git a/.github/workflows/iac-pipeline-infrastructure-monitor-exporter.yml b/.github/workflows/iac-pipeline-infrastructure-monitor-exporter.yml index cfb15778..e9501f34 100644 --- a/.github/workflows/iac-pipeline-infrastructure-monitor-exporter.yml +++ b/.github/workflows/iac-pipeline-infrastructure-monitor-exporter.yml @@ -13,10 +13,41 @@ on: description: 'Whether to perform a dry-run' required: false default: 'true' + workflow_run: + workflows: + - Provision Monitor Server Infrastructure + types: + - completed jobs: + verify-dependencies: + name: Verify dependency workflows + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + outputs: + should-run: ${{ steps.evaluate.outputs.should-run }} + steps: + - name: Checkout helpers + uses: actions/checkout@v4 + with: + sparse-checkout: | + .github/scripts/evaluate-workflow-status.js + sparse-checkout-cone-mode: false + - name: Evaluate upstream workflow status + id: evaluate + uses: actions/github-script@v7 + with: + script: | + const { evaluateWorkflowStatus } = require('./.github/scripts/evaluate-workflow-status'); + await evaluateWorkflowStatus({ github, context, core }, { + dependencyWorkflowFile: 'iac-pipeline-infrastructure-monitor-server.yml', + }); + deploy: - if: github.ref == 'refs/heads/main' + needs: verify-dependencies + if: needs.verify-dependencies.outputs.should-run == 'true' runs-on: ubuntu-latest env: DEPLOY_ACTION: ${{ github.event.inputs.deploy_action || 'upgrade' }} diff --git a/.github/workflows/iac-pipeline-infrastructure-monitor-server.yml b/.github/workflows/iac-pipeline-infrastructure-monitor-server.yml index d99d4f1c..17414b1c 100644 --- a/.github/workflows/iac-pipeline-infrastructure-monitor-server.yml +++ b/.github/workflows/iac-pipeline-infrastructure-monitor-server.yml @@ -11,6 +11,11 @@ on: description: "Run Ansible in check mode" required: false default: 'true' + workflow_run: + workflows: + - MultiCluster Pipeline Create with IAC tools + types: + - completed push: branches: - main @@ -25,15 +30,44 @@ env: ANSIBLE_LOAD_CALLBACK_PLUGINS: 'true' jobs: + verify-dependencies: + name: Verify dependency workflows + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + outputs: + should-run: ${{ steps.evaluate.outputs.should-run }} + steps: + - name: Checkout helpers + uses: actions/checkout@v4 + with: + sparse-checkout: | + .github/scripts/evaluate-workflow-status.js + sparse-checkout-cone-mode: false + - name: Evaluate upstream workflow status + id: evaluate + uses: actions/github-script@v7 + with: + script: | + const { evaluateWorkflowStatus } = require('./.github/scripts/evaluate-workflow-status'); + await evaluateWorkflowStatus({ github, context, core }, { + dependencyWorkflowFile: 'iac-pipeline-create.yml', + }); + pre-setup: + needs: verify-dependencies + if: needs.verify-dependencies.outputs.should-run == 'true' runs-on: ubuntu-latest steps: - name: Pre-setup confirmation run: echo "Pre-setup stage completed" deploy: - needs: pre-setup - if: github.ref == 'refs/heads/main' + needs: + - pre-setup + - verify-dependencies + if: needs.verify-dependencies.outputs.should-run == 'true' runs-on: ubuntu-latest strategy: matrix: