nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at release-25.11 213 lines 7.2 kB view raw
1/// @ts-check 2 3// TODO: should this be combined with the branch checks in prepare.js? 4// They do seem quite similar, but this needs to run after eval, 5// and prepare.js obviously doesn't. 6 7const { classify, split } = require('../supportedBranches.js') 8const { readFile } = require('node:fs/promises') 9const { postReview, dismissReviews } = require('./reviews.js') 10 11const reviewKey = 'check-target-branch' 12/** 13 * @param {{ 14 * github: InstanceType<import('@actions/github/lib/utils').GitHub>, 15 * context: import('@actions/github/lib/context').Context 16 * core: import('@actions/core') 17 * dry: boolean 18 * }} CheckTargetBranchProps 19 */ 20async function checkTargetBranch({ github, context, core, dry }) { 21 /** 22 * @type {{ 23 * attrdiff: { 24 * added: string[], 25 * changed: string[], 26 * removed: string[], 27 * }, 28 * labels: Record<string, boolean>, 29 * rebuildCountByKernel: Record<string, number>, 30 * rebuildsByKernel: Record<string, string[]>, 31 * rebuildsByPlatform: Record<string, string[]>, 32 * }} 33 */ 34 const changed = JSON.parse( 35 await readFile('comparison/changed-paths.json', 'utf-8'), 36 ) 37 const pull_number = context.payload.pull_request?.number 38 if (!pull_number) { 39 core.warning( 40 'Skipping checkTargetBranch: no pull_request number (is this being run as part of a merge group?)', 41 ) 42 return 43 } 44 const prInfo = ( 45 await github.rest.pulls.get({ 46 ...context.repo, 47 pull_number, 48 }) 49 ).data 50 const base = prInfo.base.ref 51 const head = prInfo.head.ref 52 const baseClassification = classify(base) 53 const headClassification = classify(head) 54 55 // Don't run on, e.g., staging-nixos to master merges. 56 if (headClassification.type.includes('development')) { 57 core.info( 58 `Skipping checkTargetBranch: PR is from a development branch (${head})`, 59 ) 60 61 await dismissReviews({ 62 github, 63 context, 64 core, 65 dry, 66 reviewKey, 67 }) 68 69 return 70 } 71 // Don't run on PRs against staging branches, wip branches, haskell-updates, etc. 72 if (!baseClassification.type.includes('primary')) { 73 core.info( 74 `Skipping checkTargetBranch: PR is against a non-primary base branch (${base})`, 75 ) 76 77 await dismissReviews({ 78 github, 79 context, 80 core, 81 dry, 82 reviewKey, 83 }) 84 85 return 86 } 87 88 const maxRebuildCount = Math.max( 89 ...Object.values(changed.rebuildCountByKernel), 90 ) 91 const rebuildsAllTests = 92 changed.attrdiff.changed.includes('nixosTests.simple') 93 94 // https://github.com/NixOS/nixpkgs/pull/481205#issuecomment-3790123921 95 // These should go to staging-nixos instead of master, 96 // but release-xx.xx (not staging-xx.xx) when backported 97 let isExemptKernelUpdate = false 98 if (prInfo.changed_files === 1 && base.startsWith('release-')) { 99 const changedFiles = ( 100 await github.rest.pulls.listFiles({ 101 ...context.repo, 102 pull_number, 103 }) 104 ).data 105 isExemptKernelUpdate = 106 changedFiles.length === 1 && 107 changedFiles[0].filename === 108 'pkgs/os-specific/linux/kernel/kernels-org.json' 109 } 110 111 // https://github.com/NixOS/nixpkgs/pull/483194#issuecomment-3793393218 112 const isExemptHomeAssistantUpdate = 113 maxRebuildCount <= 1500 && head === 'wip-home-assistant' 114 115 core.info( 116 [ 117 `checkTargetBranch: this PR:`, 118 ` * causes ${maxRebuildCount} rebuilds`, 119 ` * ${rebuildsAllTests ? 'rebuilds' : 'does not rebuild'} all NixOS tests`, 120 ` * ${isExemptKernelUpdate ? 'is' : 'is not'} an exempt kernel update`, 121 ` * ${isExemptHomeAssistantUpdate ? 'is' : 'is not'} an exempt home-assistant update`, 122 ].join('\n'), 123 ) 124 125 if ( 126 maxRebuildCount >= 1000 && 127 !isExemptHomeAssistantUpdate && 128 !isExemptKernelUpdate 129 ) { 130 const desiredBranch = 131 base === 'master' ? 'staging' : `staging-${split(base).version}` 132 const body = [ 133 `The PR's base branch is set to \`${base}\`, but this PR causes ${maxRebuildCount} rebuilds.`, 134 'It is therefore considered a mass rebuild.', 135 `Please [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to [the right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions) (probably \`${desiredBranch}\`).`, 136 ].join('\n') 137 138 await postReview({ 139 github, 140 context, 141 core, 142 dry, 143 body, 144 event: 'COMMENT', 145 reviewKey, 146 }) 147 148 throw new Error('This PR is against the wrong branch.') 149 } else if (rebuildsAllTests && !isExemptKernelUpdate) { 150 let branchText 151 if (base === 'master' && maxRebuildCount >= 500) { 152 branchText = '(probably either `staging-nixos` or `staging`)' 153 } else if (base === 'master') { 154 branchText = '(probably `staging-nixos`)' 155 } else { 156 branchText = `(probably \`staging-${split(base).version}\`)` 157 } 158 const body = [ 159 `The PR's base branch is set to \`${base}\`, but this PR rebuilds all NixOS tests.`, 160 base === 'master' && maxRebuildCount >= 500 161 ? `Since this PR also causes ${maxRebuildCount} rebuilds, it may also be considered a mass rebuild.` 162 : '', 163 `Please [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to [the right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions) ${branchText}.`, 164 ].join('\n') 165 166 await postReview({ 167 github, 168 context, 169 core, 170 dry, 171 body, 172 event: 'COMMENT', 173 reviewKey, 174 }) 175 176 throw new Error('This PR is against the wrong branch.') 177 } else if ( 178 maxRebuildCount >= 500 && 179 !isExemptKernelUpdate && 180 !isExemptHomeAssistantUpdate 181 ) { 182 const stagingBranch = 183 base === 'master' ? 'staging' : `staging-${split(base).version}` 184 const body = [ 185 `The PR's base branch is set to \`${base}\`, and this PR causes ${maxRebuildCount} rebuilds.`, 186 `Please consider whether this PR causes a mass rebuild according to [our conventions](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions).`, 187 `If it does cause a mass rebuild, please [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to [the right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions) (probably \`${stagingBranch}\`).`, 188 `If it does not cause a mass rebuild, this message can be ignored.`, 189 ].join('\n') 190 191 await postReview({ 192 github, 193 context, 194 core, 195 dry, 196 body, 197 event: 'COMMENT', 198 reviewKey, 199 }) 200 } else { 201 core.info('checkTargetBranch: this PR is against an appropriate branch.') 202 203 await dismissReviews({ 204 github, 205 context, 206 core, 207 dry, 208 reviewKey, 209 }) 210 } 211} 212 213module.exports = checkTargetBranch