Unverified Commit b24205e0 authored by nixpkgs-ci[bot]'s avatar nixpkgs-ci[bot] Committed by GitHub
Browse files

Merge master into staging-next

parents e69b54bf b780d509
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -576,7 +576,10 @@ module.exports = async ({ github, context, core, dry }) => {

  // Controls level of parallelism. Applies to both the number of concurrent requests
  // as well as the number of concurrent workers going through the list of PRs.
  const maxConcurrent = 20
  // We'll only boost concurrency when we're running many PRs in parallel on a schedule,
  // but not for single PRs. This avoids things going wild, when we accidentally make
  // too many API requests on treewides.
  const maxConcurrent = context.payload.pull_request ? 1 : 20

  await withRateLimit({ github, core, maxConcurrent }, async (stats) => {
    if (context.payload.pull_request) {
+24 −8
Original line number Diff line number Diff line
@@ -128,11 +128,20 @@ async function handleMerge({
    (await getTeamMembers('nixpkgs-committers')).map(({ id }) => id),
  )

  const files = await github.paginate(github.rest.pulls.listFiles, {
  const files = (
    await github.rest.pulls.listFiles({
      ...context.repo,
      pull_number,
      per_page: 100,
    })
  ).data

  // Early exit to prevent treewides from using up a lot of API requests (and time!) to list
  // all the files in the pull request. For now, the merge-bot will not work when 100 or more
  // files are touched in a PR - which should be more than fine.
  // TODO: Find a more efficient way of downloading all the *names* of the touched files,
  // including an early exit when the first non-by-name file is found.
  if (files.length >= 100) return false

  // Only look through comments *after* the latest (force) push.
  const lastPush = events.findLastIndex(
@@ -182,7 +191,9 @@ async function handleMerge({
        }`,
        { node_id: pull_request.node_id, sha: pull_request.head.sha },
      )
      return `[Queued](${resp.enqueuePullRequest.mergeQueueEntry.mergeQueue.url}) for merge`
      return [
        `:heavy_check_mark: [Queued](${resp.enqueuePullRequest.mergeQueueEntry.mergeQueue.url}) for merge (#306934)`,
      ]
    } catch (e) {
      log('Enqueing failed', e.response.errors[0].message)
    }
@@ -201,7 +212,12 @@ async function handleMerge({
        }`,
        { node_id: pull_request.node_id, sha: pull_request.head.sha },
      )
      return 'Enabled Auto Merge'
      return [
        `:heavy_check_mark: Enabled Auto Merge (#306934)`,
        '',
        '> [!TIP]',
        '> Sometimes GitHub gets stuck after enabling Auto Merge. In this case, leaving another approval should trigger the merge.',
      ]
    } catch (e) {
      log('Auto Merge failed', e.response.errors[0].message)
      throw new Error(e.response.errors[0].message)
@@ -287,7 +303,7 @@ async function handleMerge({
    if (result) {
      await react('ROCKET')
      try {
        body.push(`:heavy_check_mark: ${await merge()} (#306934)`)
        body.push(...(await merge()))
      } catch (e) {
        // Remove the HTML comment with node_id reference to allow retrying this merge on the next run.
        body.shift()
+35 −20
Original line number Diff line number Diff line
@@ -13,6 +13,34 @@ async function handleReviewers({
}) {
  const pull_number = pull_request.number

  const requested_reviewers = new Set(
    pull_request.requested_reviewers.map(({ login }) => login),
  )
  log(
    'reviewers - requested_reviewers',
    Array.from(requested_reviewers).join(', '),
  )

  const existing_reviewers = new Set(
    reviews.map(({ user }) => user?.login).filter(Boolean),
  )
  log(
    'reviewers - existing_reviewers',
    Array.from(existing_reviewers).join(', '),
  )

  // Early sanity check, before we start making any API requests. The list of maintainers
  // does not have duplicates so the only user to filter out from this list would be the
  // PR author. Therefore, we check for a limit of 15+1, where 15 is the limit we check
  // further down again.
  // This is to protect against huge treewides consuming all our API requests for no
  // reason.
  if (maintainers.length > 16) {
    core.warning('Too many potential reviewers, skipping review requests.')
    // Return a boolean on whether the "needs: reviewers" label should be set.
    return existing_reviewers.size === 0 && requested_reviewers.size === 0
  }

  const users = new Set([
    ...(await Promise.all(
      maintainers.map(async (id) => (await getUser(id)).login),
@@ -47,6 +75,9 @@ async function handleReviewers({
  const reviewers = (
    await Promise.all(
      Array.from(new_reviewers, async (username) => {
        // TODO: Restructure this file to only do the collaborator check for those users
        // who were not already part of a team. Being a member of a team makes them
        // collaborators by definition.
        try {
          await github.rest.repos.checkCollaborator({
            ...context.repo,
@@ -65,29 +96,13 @@ async function handleReviewers({
  log('reviewers - reviewers', reviewers.join(', '))

  if (reviewers.length > 15) {
    log(
    core.warning(
      `Too many reviewers (${reviewers.join(', ')}), skipping review requests.`,
    )
    // false indicates, that we do have reviewers and don't need the "needs: reviewers" label.
    return false
    // Return a boolean on whether the "needs: reviewers" label should be set.
    return existing_reviewers.size === 0 && requested_reviewers.size === 0
  }

  const requested_reviewers = new Set(
    pull_request.requested_reviewers.map(({ login }) => login),
  )
  log(
    'reviewers - requested_reviewers',
    Array.from(requested_reviewers).join(', '),
  )

  const existing_reviewers = new Set(
    reviews.map(({ user }) => user?.login).filter(Boolean),
  )
  log(
    'reviewers - existing_reviewers',
    Array.from(existing_reviewers).join(', '),
  )

  const non_requested_reviewers = new Set(reviewers)
    .difference(requested_reviewers)
    // We don't want to rerequest reviews from people who already reviewed.
@@ -117,7 +132,7 @@ async function handleReviewers({

  // Return a boolean on whether the "needs: reviewers" label should be set.
  return (
    new_reviewers.size === 0 &&
    non_requested_reviewers.size === 0 &&
    existing_reviewers.size === 0 &&
    requested_reviewers.size === 0
  )
+28 −9
Original line number Diff line number Diff line
@@ -763,11 +763,26 @@ rec {
    # Inputs

    `extendMkDerivation`-specific configurations
    : `constructDrv`: Base build helper, the `mkDerivation`-like build helper to extend.
    : `excludeDrvArgNames`: Argument names not to pass from the input fixed-point arguments to `constructDrv`. Note: It doesn't apply to the updating arguments returned by `extendDrvArgs`.
    : `extendDrvArgs` : An extension (overlay) of the argument set, like the one taken by [overrideAttrs](#sec-pkg-overrideAttrs) but applied before passing to `constructDrv`.
    : `inheritFunctionArgs`: Whether to inherit `__functionArgs` from the base build helper (default to `true`).
    : `transformDrv`: Function to apply to the result derivation (default to `lib.id`).
    : `constructDrv` (required)
      : Base build helper, the `mkDerivation`-like build helper to extend.

      `excludeDrvArgNames` (default to `[ ]`)
      : Argument names not to pass from the input fixed-point arguments to `constructDrv`.
        It doesn't apply to the updating arguments returned by `extendDrvArgs`.

      `excludeFunctionArgNames` (default to `[ ]`)
      : `__functionArgs` attribute names to remove from the result build helper.
        `excludeFunctionArgNames` is useful for argument deprecation while avoiding ellipses.

      `extendDrvArgs` (required)
      : An extension (overlay) of the argument set, like the one taken by [overrideAttrs](#sec-pkg-overrideAttrs) but applied before passing to `constructDrv`.

      `inheritFunctionArgs` (default to `true`)
      : Whether to inherit `__functionArgs` from the base build helper.
        Set `inheritFunctionArgs` to `false` when `extendDrvArgs`'s `args` set pattern does not contain an ellipsis.

      `transformDrv` (default to `lib.id`)
      : Function to apply to the result derivation.

    # Type

@@ -776,6 +791,7 @@ rec {
      {
        constructDrv :: ((FixedPointArgs | AttrSet) -> a)
        excludeDrvArgNames :: [ String ],
        excludeFunctionArgNames :: [ String ]
        extendDrvArgs :: (AttrSet -> AttrSet -> AttrSet)
        inheritFunctionArgs :: Bool,
        transformDrv :: a -> a,
@@ -836,6 +852,7 @@ rec {
    {
      constructDrv,
      excludeDrvArgNames ? [ ],
      excludeFunctionArgNames ? [ ],
      extendDrvArgs,
      inheritFunctionArgs ? true,
      transformDrv ? id,
@@ -850,10 +867,12 @@ rec {
      )
      # Add __functionArgs
      (
        removeAttrs (
          # Inherit the __functionArgs from the base build helper
          optionalAttrs inheritFunctionArgs (removeAttrs (functionArgs constructDrv) excludeDrvArgNames)
          # Recover the __functionArgs from the derived build helper
          // functionArgs (extendDrvArgs { })
        ) excludeFunctionArgNames
      )
    // {
      inherit
+9 −0
Original line number Diff line number Diff line
@@ -223,6 +223,15 @@ checkConfigError 'A definition for option .* is not of type .path in the Nix sto
checkConfigError 'A definition for option .* is not of type .path in the Nix store.. Definition values:\n\s*- In .*: ".*/store/.links"' config.pathInStore.bad4 ./types.nix
checkConfigError 'A definition for option .* is not of type .path in the Nix store.. Definition values:\n\s*- In .*: "/foo/bar"' config.pathInStore.bad5 ./types.nix

# types.externalPath
checkConfigOutput '".*/foo/bar"' config.externalPath.ok1 ./types.nix
checkConfigOutput '".*/"' config.externalPath.ok2 ./types.nix
checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad1 ./types.nix
checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad2 ./types.nix
checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad3 ./types.nix
checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad4 ./types.nix
checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad5 ./types.nix

# types.fileset
checkConfigOutput '^0$' config.filesetCardinal.ok1 ./fileset.nix
checkConfigOutput '^1$' config.filesetCardinal.ok2 ./fileset.nix
Loading