From dd85b07f3150bb3cd6986ff3d8eb9afdd8206ff2 Mon Sep 17 00:00:00 2001 From: Kurdistan Tech Ministry Date: Thu, 27 Nov 2025 15:41:02 +0300 Subject: [PATCH] Initial workflow-stopper setup for Pezkuwi SDK CI/CD --- .github/workflows/stopper.yml | 93 +++++++++++++++++++++++++++++++++++ README.md | 35 +++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 .github/workflows/stopper.yml create mode 100644 README.md diff --git a/.github/workflows/stopper.yml b/.github/workflows/stopper.yml new file mode 100644 index 0000000..ae22be4 --- /dev/null +++ b/.github/workflows/stopper.yml @@ -0,0 +1,93 @@ +name: Workflow Stopper + +on: + workflow_dispatch: + inputs: + github_sha: + description: 'The SHA of the commit to stop workflows for' + required: true + github_repository: + description: 'The repository (owner/repo) to stop workflows in' + required: true + github_ref_name: + description: 'The ref name (branch) to stop workflows for' + required: true + github_workflow_id: + description: 'The workflow run ID that triggered this' + required: true + github_job_name: + description: 'The job name that triggered this' + required: true + +jobs: + stop-workflows: + runs-on: ubuntu-latest + steps: + - name: Cancel running workflows + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.WORKFLOW_STOPPER_TOKEN }} + script: | + const [owner, repo] = '${{ github.event.inputs.github_repository }}'.split('/'); + const sha = '${{ github.event.inputs.github_sha }}'; + const triggerRunId = '${{ github.event.inputs.github_workflow_id }}'; + const triggerJob = '${{ github.event.inputs.github_job_name }}'; + + console.log(`Stopping workflows for ${owner}/${repo} at SHA ${sha}`); + console.log(`Triggered by run ${triggerRunId}, job ${triggerJob}`); + + // Get all running workflow runs for this SHA + const { data: runs } = await github.rest.actions.listWorkflowRunsForRepo({ + owner, + repo, + status: 'in_progress', + head_sha: sha, + per_page: 100 + }); + + console.log(`Found ${runs.workflow_runs.length} running workflows`); + + // Cancel each running workflow (except the trigger) + for (const run of runs.workflow_runs) { + if (run.id.toString() === triggerRunId) { + console.log(`Skipping trigger workflow run ${run.id}`); + continue; + } + + try { + await github.rest.actions.cancelWorkflowRun({ + owner, + repo, + run_id: run.id + }); + console.log(`Cancelled workflow run ${run.id} (${run.name})`); + } catch (error) { + console.log(`Failed to cancel run ${run.id}: ${error.message}`); + } + } + + // Also get queued workflows + const { data: queuedRuns } = await github.rest.actions.listWorkflowRunsForRepo({ + owner, + repo, + status: 'queued', + head_sha: sha, + per_page: 100 + }); + + console.log(`Found ${queuedRuns.workflow_runs.length} queued workflows`); + + for (const run of queuedRuns.workflow_runs) { + try { + await github.rest.actions.cancelWorkflowRun({ + owner, + repo, + run_id: run.id + }); + console.log(`Cancelled queued workflow run ${run.id} (${run.name})`); + } catch (error) { + console.log(`Failed to cancel queued run ${run.id}: ${error.message}`); + } + } + + console.log('Workflow stopping complete'); diff --git a/README.md b/README.md new file mode 100644 index 0000000..f3c209e --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Pezkuwi Workflow Stopper + +Stops all running and queued workflows in a repository when a CI job fails. This saves compute resources by preventing unnecessary workflow runs from continuing after a failure is detected. + +## How It Works + +1. When a CI job fails in `pezkuwi-sdk`, the `workflow-stopper` action is triggered +2. This action dispatches a workflow in this repository +3. The workflow uses GitHub API to cancel all running/queued workflows for the same commit SHA + +## Setup + +### Required Secrets + +In this repository (`pezkuwichain/workflow-stopper`): +- `WORKFLOW_STOPPER_TOKEN` - A GitHub PAT or App token with `actions:write` permission on `pezkuwichain/pezkuwi-sdk` + +In the target repository (`pezkuwichain/pezkuwi-sdk`): +- `WORKFLOW_STOPPER_RUNNER_APP_ID` - GitHub App ID +- `WORKFLOW_STOPPER_RUNNER_APP_KEY` - GitHub App private key + +### GitHub App Setup + +1. Create a GitHub App in your organization settings +2. Grant it `actions:write` permission +3. Install it on both `workflow-stopper` and `pezkuwi-sdk` repositories +4. Add the App ID and private key as secrets + +## Usage + +This workflow is triggered via `workflow_dispatch` from the `pezkuwi-sdk` repository's CI pipelines. + +## License + +Apache-2.0 (same as Pezkuwi SDK)