Używam Wtyczka Multilibranch, aby zeskanować nowe żądania pull i muszę ograniczyć moje budowania zatwierdzone tylko pociągnij żądania. Filtruję zatwierdzone żądania pull po ich skanowaniu, jednak skaner repozytorium może jedynie określić, czy żądanie pull ma nowe zobowiązania.

Próbowałem PR Komentarze Buduj wtyczkę i dodałem Trigger build on pull request review Nieruchomość do źródła oddziału Githuba nie jest dostępna - wydaje się, że dodanie tej właściwości nie ma żadnego wpływu na sposoby przetwarzania skanera żądania.

Czy mogę powiedzieć skaner repozytorium, aby wywołać kompilację na nowych opiniach? Czy jest jakiś inny sposób zbudowania żądań ciągnięcia dopiero po zatwierdzeniu?

Dzięki!

2
towel 26 grudzień 2019, 16:07

1 odpowiedź

Najlepsza odpowiedź

Musiałem zaakceptować, że nie było sposobu, aby skanowanie oddziału rozważyło obiekty nie-git (takie jak recenzje Github).

Skończyło się na podejmowaniu rurociągu, który utrzymywał listę wszystkich jeszcze zatwierdzonych próśb ciągłych (przy użyciu interfejsu API GitHub), a po zatwierdzeniu żądania pull wywołuje na nim budowanie.

Czuje hacky, ale niestety był jedynym sposobem, w jaki mógłbym pomyśleć o budowę tylko na zatwierdzeniu ... Ważna uwaga: To rozwiązanie wymaga istniejącego zadania multibrangu do pracy. Więc to właśnie zrobiłem:

Pierwsze zapytanie dotyczące istniejących żądań pullowych i ich statusu (zainstalować HTTPREQUEST wtyczka):

// Send a query to github and get the response JSON
def githubQuery(Map args = [:]) {
  def formattedQuery = args.query.replaceAll('\n', ' ').replaceAll('"', '\\\\"')
  def response = httpRequest(
    authentication: args.auth,
    httpMode: 'POST',
    requestBody: """{ "query": "${formattedQuery}" }""",
    url: "https://api.github.com/graphql"
  )
  (response.status == 200) ? readJSON(text: response.content) : [:]
}

def getPRStatus(Map args = [:]) {
  // Build the query to get all open pull requests and their status
  def query = """query {
    organization(login: "${args.organization}") {
      repositories(first: 30) {
        nodes {
          name
          pullRequests(first: 100, states: [OPEN]) {
            nodes {
              number
              state
              reviews(first: 10, states: [APPROVED]) {
                totalCount
              }
            }
          }
        }
      }
    }
  }"""
  def response = githubQuery(args + [query: query])
  def repositories = response?.data.organization.repositories.nodes
  // Organize the pull requests into approved and unapproved groups
  repositories?.collectEntries { repo ->
    // Take out draft pull requests
    def prs = repo.pullRequests.nodes.findAll { it.state != "DRAFT" }
    def repoPrs = [
      unapproved: prs.findAll { it.reviews.totalCount == 0 },
      approved: prs.findAll { it.reviews.totalCount > 0 }
    ].collectEntries { category, categoryPrs ->
      [ category, categoryPrs.collect { it.number } ]
    }
    [ repo.name, repoPrs ]
  }
}

Następnie porównaj każdy status prośby o status do jego statusu z poprzedniej ankiety i buduje tylko te, które zmieniły status do zatwierdzonego:

def monitorRecentlyApprovedPRs(Map args = [:]) {
  def prMap = getPRStatus(args)
  // Build recently approved pull requests on each repository
  prMap.each { repoName, repoPrs ->
    // Get previously unapproved pull requests
    def previouslyUnapproved = currentBuild.previousBuild?.buildVariables?."${repoName}"?.tokenize(",").collect { it.toInteger() } ?: []
    // Build recently approved pull requests
    repoPrs.approved.intersect(previouslyUnapproved).each { prNumber ->
      build job: "/${args.multibranch}/PR-${prNumber}", wait: false
    }
    env."${repoName}" = repoPrs.unapproved.join(",")
  }
}

Podczas dzwonienia {X0}} Musisz dostarczyć te argumenty:

monitorRecentlyApprovedPRs organization: "YOUR-ORGANIZATION", auth: "GITHUB-CREDENTIALS", multibranch: "PATH-TO-THE-MULTIBRANCH-JOB-IN-JENKINS"

Wreszcie zaktualizuj multibranch's Jenkinsfile, aby pominąć niezatwierdzone PRS:

def shouldBuildPR(Map args = [:]) {
  // Get pull request info
  def query = """query {
    organization(login: "${args.organization}") {
      repository(name: "${args.repo}") {
        pullRequest(number: ${args.pr}) {
          state
          reviews(first: 10, states: [APPROVED]) {
            totalCount
          }
        }
      }
    }
  }"""
  def response = githubQuery(args + [query: query])
  def prInfo = response?.data.organization.repository.pullRequest
  def shouldBuild = (
    // Skip merged pull requests
    prInfo.state != "MERGED" &&
    // Check for draft state
    (prInfo.state != "DRAFT") &&
    // Check for approval
    (prInfo.reviews.totalCount > 0)
  )
  shouldBuild
}

Zadzwonić shouldBuildPR Zapewniesz te argumenty:

shouldBuildPR(organization: "YOUR-ORGANIZATION", repo: "PR-REPO", auth: "GITHUB-CREDENTIALS", pr: env.CHANGE_ID)

Jeśli zwrócona wartość jest false powinieneś zatrzymać resztę wykonania rurociągu. Rzeczy byłyby bardzo prostsze, jeśli wtyczka rurociągów Multilibrance zapewniła zmienną środowiskową PR :)

2
towel 21 styczeń 2020, 11:26