72 lines
2.9 KiB
YAML
72 lines
2.9 KiB
YAML
name: Prevent Invalid Merges
|
|
|
|
on:
|
|
pull_request:
|
|
types: [opened, reopened, synchronize, edited]
|
|
|
|
jobs:
|
|
validate-merge-flow:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Validate Branch Flow
|
|
uses: actions/github-script@v7
|
|
with:
|
|
script: |
|
|
const base = context.payload.pull_request.base.ref;
|
|
const head = context.payload.pull_request.head.ref;
|
|
|
|
core.info(`Checking Merge Flow: ${head} -> ${base}`);
|
|
|
|
// 1. Parse module name from base branch
|
|
// Expected formats: dev_X, preprod_X, master_X
|
|
const tiers = ["dev", "preprod", "master"];
|
|
|
|
function parseBranch(branchName) {
|
|
for (const tier of tiers) {
|
|
if (branchName.startsWith(tier + "_")) {
|
|
return { tier: tier, module: branchName.substring(tier.length + 1) };
|
|
}
|
|
}
|
|
return null; // Not a standard environment branch (maybe feature/fix)
|
|
}
|
|
|
|
const baseInfo = parseBranch(base);
|
|
const headInfo = parseBranch(head);
|
|
|
|
// If base is not a protected tier (dev/preprod/master), allow merge (feature -> feature)
|
|
if (!baseInfo) {
|
|
core.info("Base branch is not a protected environment tier. Merge allowed.");
|
|
return;
|
|
}
|
|
|
|
// Logic for Protected Base Branches
|
|
|
|
// ❌ Rule: Cannot merge directly into master from anywhere except preprod (of same module)
|
|
if (baseInfo.tier === "master") {
|
|
if (!headInfo || headInfo.tier !== "preprod" || headInfo.module !== baseInfo.module) {
|
|
core.setFailed(`❌ Forbidden: You can ONLY merge into 'master_${baseInfo.module}' from 'preprod_${baseInfo.module}'. Detected: ${head}`);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// ❌ Rule: Cannot merge directly into preprod from anywhere except dev (of same module)
|
|
if (baseInfo.tier === "preprod") {
|
|
if (!headInfo || headInfo.tier !== "dev" || headInfo.module !== baseInfo.module) {
|
|
core.setFailed(`❌ Forbidden: You can ONLY merge into 'preprod_${baseInfo.module}' from 'dev_${baseInfo.module}'. Detected: ${head}`);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// ❌ Rule: Cannot merge directly into dev from master or preprod (reverse flow)
|
|
// (Optional: You might allow hotfixes, but strictly strictly dev<-feature is best)
|
|
if (baseInfo.tier === "dev") {
|
|
// Allow feature branches to merge into dev
|
|
// Block upstream branches
|
|
if (headInfo && (headInfo.tier === "master" || headInfo.tier === "preprod")) {
|
|
core.setFailed(`❌ Forbidden: Cannot merge upstream (${head}) back into dev.`);
|
|
return;
|
|
}
|
|
}
|
|
|
|
core.info("✅ Merge flow validation passed.");
|