Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions .github/workflows/stable-branch-gate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
name: Stable Branch Gate

# This workflow ensures that PRs to the stable branch cannot be merged
# until the remote stable-merge-check workflow has completed successfully
on:
pull_request:
branches: [stable]
types: [opened, synchronize, reopened, ready_for_review]

permissions:
contents: read
pull-requests: write
checks: write
issues: write

jobs:
check-remote-workflow-status:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might have missed it, but if the check upon PR open fails, can we retrigger it after having it opened?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the check actually should not fail if the remote branch exists, I can add a polling wait for the remote workflow to either fail/pass though if the branch exists

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct me if I'm wrong but, in this scenario:

  • I create a PR from main -> stable in dspo
  • this is triggered, the workflow then checks workflows in dsp that are also running for a similar pr that target dsp main
  • if it doesn't find any runs, or if any runs failed, it fails the check

Suppose I re-run the DSP CI on the DSP pr from master -> stable, and I want to retrigger this check on the DSPO master, how would I do that?

name: Check Remote Integration Tests
runs-on: ubuntu-latest

# Only run on PRs targeting stable branch
if: github.event.pull_request.base.ref == 'stable'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't we also want to confirm that the head ref is main? otherwise this workflow will fail right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For hot fixes or cherry picks, the head ref will not be main, so I think we should run this check for all prs to stable branch


steps:
- name: Check remote workflow status
id: check-remote
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
// Get PR information
const prNumber = context.payload.pull_request.number;
const headSha = context.payload.pull_request.head.sha;
const headRef = context.payload.pull_request.head.ref;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the default branch in dspo is main whereas in dsp it's master wouldn't this break?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, I will make that change

Copy link
Contributor

@HumairAK HumairAK Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry this will be stable, which is what we want I think


console.log(`Checking remote workflow status for PR #${prNumber}`);
console.log(`Head SHA: ${headSha}`);
console.log(`Head Ref: ${headRef}`);

try {
const remoteOwner = 'opendatahub-io';
const remoteRepo = 'data-science-pipelines';

// Map branch name: if headRef is 'main', use 'master' for remote repo
const remoteBranch = headRef === 'main' ? 'master' : headRef;
console.log(`Remote branch to check: ${remoteBranch}`);

// Try to get workflow runs for the stable-merge-check workflow
const { data: workflows } = await github.rest.actions.listWorkflowRuns({
owner: remoteOwner,
repo: remoteRepo,
workflow_id: 'stable-merge-check.yml',
branch: remoteBranch, // Look for runs on the mapped branch name
per_page: 20
});
Comment on lines +49 to +55
Copy link
Contributor

@HumairAK HumairAK Nov 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm a bit confused, so stable-merge-check.yml runs on a pull request to stable in DSP, but doesn't the above code search runs on the stable branch (i.e. if we ran this check post-merge on stable)? would that work?


console.log(`Found ${workflows.total_count} workflow runs for branch ${headRef}`);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix misleading log message.

Line 57 logs headRef but the code actually queries remoteBranch (which may differ when headRef is 'main'). Update the log to reflect what was actually queried:

-            console.log(`Found ${workflows.total_count} workflow runs for branch ${headRef}`);
+            console.log(`Found ${workflows.total_count} workflow runs for branch ${remoteBranch}`);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.log(`Found ${workflows.total_count} workflow runs for branch ${headRef}`);
console.log(`Found ${workflows.total_count} workflow runs for branch ${remoteBranch}`);
🤖 Prompt for AI Agents
.github/workflows/stable-branch-gate.yml around line 57: the log prints headRef
but the workflow query used remoteBranch, causing a misleading message when
headRef differs (e.g., 'main'). Change the log to reference the actual variable
used in the query (remoteBranch) and include both values if helpful (e.g.,
remoteBranch and headRef) so the message accurately reflects which branch was
queried.


// Look for successful runs
const successfulRuns = workflows.workflow_runs.filter(run =>
run.conclusion === 'success' &&
run.status === 'completed'
);

if (successfulRuns.length > 0) {
const latestSuccessful = successfulRuns[0];
console.log(`✅ Found ${successfulRuns.length} successful remote workflow run(s)`);
console.log(`Latest successful run: ${latestSuccessful.html_url}`);
core.setOutput('status', 'success');
core.setOutput('message', `Remote integration tests passed`);
core.setOutput('workflow_url', latestSuccessful.html_url);
} else {
// Check for any runs at all
const anyRuns = workflows.workflow_runs.length > 0;
if (anyRuns) {
const latestRun = workflows.workflow_runs[0];
console.log(`❌ No successful runs found. Latest run status: ${latestRun.status}, conclusion: ${latestRun.conclusion}`);
core.setOutput('status', 'failure');
core.setOutput('message', `Remote integration tests have not passed (status: ${latestRun.conclusion || latestRun.status})`);
core.setOutput('workflow_url', latestRun.html_url);
} else {
console.log('❌ No workflow runs found for this branch');
core.setOutput('status', 'failure');
core.setOutput('message', 'No remote integration test runs found for this branch');
core.setOutput('workflow_url', `https://github.com/${remoteOwner}/${remoteRepo}/actions/workflows/stable-merge-check.yml`);
}
}
} catch (error) {
console.error(`Error checking workflow status: ${error.message}`);
core.setOutput('status', 'failure');
core.setOutput('message', `Error checking remote integration test status: ${error.message}`);
core.setOutput('workflow_url', 'https://github.com/opendatahub-io/data-science-pipelines/actions/workflows/stable-merge-check.yml');
}

- name: Set status check
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const status = '${{ steps.check-remote.outputs.status }}';
const message = '${{ steps.check-remote.outputs.message }}';
const workflowUrl = '${{ steps.check-remote.outputs.workflow_url }}';

const state = status === 'success' ? 'success' : 'failure';

await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: context.payload.pull_request.head.sha,
state: state,
target_url: workflowUrl,
description: message,
context: 'stable-branch-gate/remote-integration-tests'
});

if (state === 'failure') {
core.setFailed(message);
}

provide-instructions:
name: Provide Instructions
runs-on: ubuntu-latest
if: github.event.pull_request.base.ref == 'stable' && github.event.action == 'opened'

steps:
- name: Comment with instructions
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.payload.pull_request.number;

const comment = `
## 🔒 Stable Branch Protection

This PR targets the **stable** branch and requires integration test verification from the upstream repository.

### Requirements:
The [stable-merge-check workflow](https://github.com/opendatahub-io/data-science-pipelines/blob/master/.github/workflows/stable-merge-check.yml) in the **opendatahub-io/data-science-pipelines** repository must complete successfully for a branch with the same name as this PR.

### How it works:
- This workflow automatically checks if the remote integration tests have passed
- If successful, the PR will be eligible for merge
- If not, ensure the corresponding branch exists in the upstream repo and tests pass there

📋 **Status**: Checking remote integration test status...
`;

await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: comment
});