diff --git a/.github/workflows/bot.yml b/.github/workflows/bot.yml index 9eb5911aadb5c..44198e2e2735a 100644 --- a/.github/workflows/bot.yml +++ b/.github/workflows/bot.yml @@ -97,7 +97,7 @@ jobs: github.event_name == 'pull_request_target' && !contains(fromJSON(inputs.headBranch).type, 'development') with: - repo-token: ${{ steps.app-token.outputs.token }} + repo-token: ${{ steps.app-token.outputs.token || github.token }} configuration-path: .github/labeler.yml # default sync-labels: true @@ -107,7 +107,7 @@ jobs: github.event_name == 'pull_request_target' && !contains(fromJSON(inputs.headBranch).type, 'development') with: - repo-token: ${{ steps.app-token.outputs.token }} + repo-token: ${{ steps.app-token.outputs.token || github.token }} configuration-path: .github/labeler-no-sync.yml sync-labels: false @@ -120,7 +120,7 @@ jobs: github.event_name == 'pull_request_target' && contains(fromJSON(inputs.headBranch).type, 'development') with: - repo-token: ${{ steps.app-token.outputs.token }} + repo-token: ${{ steps.app-token.outputs.token || github.token }} configuration-path: .github/labeler-development-branches.yml sync-labels: true diff --git a/ci/github-script/bot.js b/ci/github-script/bot.js index f0155e8edd1c4..b3c3af8ec389d 100644 --- a/ci/github-script/bot.js +++ b/ci/github-script/bot.js @@ -9,6 +9,9 @@ module.exports = async ({ github, context, core, dry }) => { const artifactClient = new DefaultArtifactClient() + // Detect if running in a fork (not NixOS/nixpkgs) + const isFork = context.repo.owner !== 'NixOS' + async function downloadMaintainerMap(branch) { let run @@ -68,9 +71,18 @@ module.exports = async ({ github, context, core, dry }) => { // We get here when none of the 10 commits we looked at contained a maintainer map. // For the master branch, we don't have any fallback options, so we error out. - // For other branches, we select a suitable fallback below. - if (branch === 'master') throw new Error('No maintainer map found.') + // In forks without merge-group history, return empty map to allow testing. + if (branch === 'master') { + if (isFork) { + core.warning( + 'No maintainer map found. Using empty map (expected in forks without merge-group history).', + ) + return {} + } + throw new Error('No maintainer map found.') + } + // For other branches, we select a suitable fallback below. const { stable, version } = classify(branch) const release = `release-${version}` @@ -109,6 +121,11 @@ module.exports = async ({ github, context, core, dry }) => { return [] } + // Forks don't have NixOS teams, return empty list + if (isFork) { + return [] + } + if (!members[team_slug]) { members[team_slug] = github.paginate(github.rest.teams.listMembersInOrg, { org: context.repo.owner, @@ -304,9 +321,37 @@ module.exports = async ({ github, context, core, dry }) => { expectedHash: artifact.digest, }) - const evalLabels = JSON.parse( + const changedPaths = JSON.parse( await readFile(`${pull_number}/changed-paths.json`, 'utf-8'), - ).labels + ) + const evalLabels = changedPaths.labels + + // Fetch all PR commits to check their messages for package patterns + const prCommits = await github.paginate(github.rest.pulls.listCommits, { + ...context.repo, + pull_number, + per_page: 100, + }) + const commitMessages = prCommits.map((c) => c.commit.message) + + // Label new package PRs: "packagename: init at X.Y.Z" + // Exclude NixOS module commits like "nixos/timekpr: init at 0.5.8" + const newPackagePattern = /(? 0 + const commitsIndicateNewPackage = commitMessages.some((msg) => + newPackagePattern.test(msg), + ) + evalLabels['8.has: package (new)'] = + hasNewPackages && commitsIndicateNewPackage + + // Label package update PRs: "packagename: X.Y.Z -> A.B.C" + // Matches versions like: 1.2.3, 0-unstable-2024-01-15, 1.3rc1, alpha, unstable + // Exclude NixOS module commits like "nixos/ncps: types.str -> types.path" + const updatePackagePattern = /(?|→) [\w.-]+/ + const commitsIndicateUpdate = commitMessages.some((msg) => + updatePackagePattern.test(msg), + ) + evalLabels['8.has: package (update)'] = commitsIndicateUpdate // TODO: Get "changed packages" information from list of changed by-name files // in addition to just the Eval results, to make this work for these packages