mirror of
https://github.com/hashicorp/vault.git
synced 2026-05-28 04:10:44 -04:00
Merge remote-tracking branch 'remotes/from/ce/main'
Some checks failed
build / setup (push) Has been cancelled
build / hcp-setup (push) Has been cancelled
CI / setup (push) Has been cancelled
Run linters / Setup (push) Has been cancelled
Run linters / Semgrep (push) Has been cancelled
Check Copywrite Headers / copywrite (push) Has been cancelled
Security Scan / scan (push) Has been cancelled
build / Check ce/* Pull Requests (push) Has been cancelled
build / ui (push) Has been cancelled
build / artifacts-ce (push) Has been cancelled
build / artifacts-ent (push) Has been cancelled
build / hcp-image (push) Has been cancelled
build / test (push) Has been cancelled
build / test-hcp-image (push) Has been cancelled
build / completed-successfully (push) Has been cancelled
CI / Run Autopilot upgrade tool (push) Has been cancelled
CI / Run Go tests (push) Has been cancelled
CI / Run Go tests tagged with testonly (push) Has been cancelled
CI / Run Go tests with data race detection (push) Has been cancelled
CI / Run Go tests with FIPS configuration (push) Has been cancelled
CI / Test UI (push) Has been cancelled
CI / tests-completed (push) Has been cancelled
Run linters / Deprecated functions (push) Has been cancelled
Run linters / Code checks (push) Has been cancelled
Run linters / Protobuf generate delta (push) Has been cancelled
Run linters / Format (push) Has been cancelled
Some checks failed
build / setup (push) Has been cancelled
build / hcp-setup (push) Has been cancelled
CI / setup (push) Has been cancelled
Run linters / Setup (push) Has been cancelled
Run linters / Semgrep (push) Has been cancelled
Check Copywrite Headers / copywrite (push) Has been cancelled
Security Scan / scan (push) Has been cancelled
build / Check ce/* Pull Requests (push) Has been cancelled
build / ui (push) Has been cancelled
build / artifacts-ce (push) Has been cancelled
build / artifacts-ent (push) Has been cancelled
build / hcp-image (push) Has been cancelled
build / test (push) Has been cancelled
build / test-hcp-image (push) Has been cancelled
build / completed-successfully (push) Has been cancelled
CI / Run Autopilot upgrade tool (push) Has been cancelled
CI / Run Go tests (push) Has been cancelled
CI / Run Go tests tagged with testonly (push) Has been cancelled
CI / Run Go tests with data race detection (push) Has been cancelled
CI / Run Go tests with FIPS configuration (push) Has been cancelled
CI / Test UI (push) Has been cancelled
CI / tests-completed (push) Has been cancelled
Run linters / Deprecated functions (push) Has been cancelled
Run linters / Code checks (push) Has been cancelled
Run linters / Protobuf generate delta (push) Has been cancelled
Run linters / Format (push) Has been cancelled
This commit is contained in:
commit
8e20a13896
4 changed files with 249 additions and 8 deletions
188
tools/pipeline/internal/pkg/github/add_assignees_test.go
Normal file
188
tools/pipeline/internal/pkg/github/add_assignees_test.go
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
// Copyright IBM Corp. 2016, 2026
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package github
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
libgithub "github.com/google/go-github/v83/github"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Test_addAssignees tests the addAssignees helper function with various input scenarios
|
||||
// including single/multiple assignees, empty lists, filtering of empty strings, and
|
||||
// deduplication of logins.
|
||||
func Test_addAssignees(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for name, test := range map[string]struct {
|
||||
logins []string
|
||||
shouldCall bool
|
||||
expectedError bool
|
||||
}{
|
||||
"single assignee": {
|
||||
logins: []string{"user1"},
|
||||
shouldCall: true,
|
||||
},
|
||||
"multiple assignees": {
|
||||
logins: []string{"user1", "user2", "user3"},
|
||||
shouldCall: true,
|
||||
},
|
||||
"empty login list": {
|
||||
logins: []string{},
|
||||
shouldCall: false,
|
||||
},
|
||||
"nil login list": {
|
||||
logins: nil,
|
||||
shouldCall: false,
|
||||
},
|
||||
"logins with empty strings": {
|
||||
logins: []string{"user1", "", "user2", ""},
|
||||
shouldCall: true, // Empty strings should be filtered out
|
||||
},
|
||||
"only empty strings": {
|
||||
logins: []string{"", "", ""},
|
||||
shouldCall: false, // All empty, should skip
|
||||
},
|
||||
"duplicate logins": {
|
||||
logins: []string{"user1", "user1", "user2"},
|
||||
shouldCall: true, // Duplicates should be compacted
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
called := false
|
||||
client, mux, teardown := setupTestClient(t)
|
||||
defer teardown()
|
||||
|
||||
if test.shouldCall {
|
||||
mux.HandleFunc("/repos/test-owner/test-repo/issues/123/assignees", func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodPost, r.Method)
|
||||
called = true
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write([]byte(`{"assignees": []}`))
|
||||
})
|
||||
}
|
||||
|
||||
err := addAssignees(
|
||||
context.Background(),
|
||||
client,
|
||||
"test-owner",
|
||||
"test-repo",
|
||||
123,
|
||||
test.logins,
|
||||
)
|
||||
|
||||
if test.expectedError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
require.Equal(t, test.shouldCall, called, "API call expectation mismatch")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test_addReviewers tests the addReviewers helper function with various input scenarios
|
||||
// including single/multiple reviewers, empty lists, filtering of empty strings, and
|
||||
// deduplication of logins.
|
||||
func Test_addReviewers(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for name, test := range map[string]struct {
|
||||
logins []string
|
||||
shouldCall bool
|
||||
expectedError bool
|
||||
}{
|
||||
"single reviewer": {
|
||||
logins: []string{"user1"},
|
||||
shouldCall: true,
|
||||
},
|
||||
"multiple reviewers": {
|
||||
logins: []string{"user1", "user2", "user3"},
|
||||
shouldCall: true,
|
||||
},
|
||||
"empty login list": {
|
||||
logins: []string{},
|
||||
shouldCall: false,
|
||||
},
|
||||
"nil login list": {
|
||||
logins: nil,
|
||||
shouldCall: false,
|
||||
},
|
||||
"logins with empty strings": {
|
||||
logins: []string{"user1", "", "user2", ""},
|
||||
shouldCall: true, // Empty strings should be filtered out
|
||||
},
|
||||
"only empty strings": {
|
||||
logins: []string{"", "", ""},
|
||||
shouldCall: false, // All empty, should skip
|
||||
},
|
||||
"duplicate logins": {
|
||||
logins: []string{"user1", "user1", "user2"},
|
||||
shouldCall: true, // Duplicates should be compacted
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
called := false
|
||||
client, mux, teardown := setupTestClient(t)
|
||||
defer teardown()
|
||||
|
||||
if test.shouldCall {
|
||||
mux.HandleFunc("/repos/test-owner/test-repo/pulls/123/requested_reviewers", func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodPost, r.Method)
|
||||
called = true
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
w.Write([]byte(`{"users": [], "teams": []}`))
|
||||
})
|
||||
}
|
||||
|
||||
err := addReviewers(
|
||||
context.Background(),
|
||||
client,
|
||||
"test-owner",
|
||||
"test-repo",
|
||||
123,
|
||||
test.logins,
|
||||
)
|
||||
|
||||
if test.expectedError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
require.Equal(t, test.shouldCall, called, "API call expectation mismatch")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// setupTestClient creates a test GitHub client with a mock HTTP server for testing.
|
||||
// It returns the client, the HTTP mux for registering handlers, and a teardown function
|
||||
// that should be called to clean up the server when the test completes.
|
||||
func setupTestClient(t *testing.T) (*libgithub.Client, *http.ServeMux, func()) {
|
||||
t.Helper()
|
||||
|
||||
mux := http.NewServeMux()
|
||||
server := httptest.NewServer(mux)
|
||||
|
||||
client := libgithub.NewClient(nil)
|
||||
serverURL, err := url.Parse(server.URL + "/")
|
||||
require.NoError(t, err)
|
||||
client.BaseURL = serverURL
|
||||
|
||||
teardown := func() {
|
||||
server.Close()
|
||||
}
|
||||
|
||||
return client, mux, teardown
|
||||
}
|
||||
39
tools/pipeline/internal/pkg/github/add_reviewers.go
Normal file
39
tools/pipeline/internal/pkg/github/add_reviewers.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright IBM Corp. 2016, 2026
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package github
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"slices"
|
||||
|
||||
libgithub "github.com/google/go-github/v83/github"
|
||||
slogctx "github.com/veqryn/slog-context"
|
||||
)
|
||||
|
||||
// addReviewers requests reviews from the given logins on the pull request
|
||||
func addReviewers(
|
||||
ctx context.Context,
|
||||
github *libgithub.Client,
|
||||
owner string,
|
||||
repo string,
|
||||
number int,
|
||||
logins []string,
|
||||
) error {
|
||||
logins = slices.Compact(slices.DeleteFunc(logins, func(a string) bool {
|
||||
return a == ""
|
||||
}))
|
||||
ctx = slogctx.Append(ctx, slog.Any("reviewer-logins", logins))
|
||||
|
||||
if len(logins) < 1 {
|
||||
slog.Default().InfoContext(ctx, "skipping pull request review requests because no logins were provided")
|
||||
return nil
|
||||
}
|
||||
|
||||
slog.Default().DebugContext(ctx, "requesting reviews on pull request")
|
||||
_, _, err := github.PullRequests.RequestReviewers(ctx, owner, repo, number, libgithub.ReviewersRequest{
|
||||
Reviewers: logins,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
|
@ -759,6 +759,20 @@ func (r *CreateBackportReq) backportRef(
|
|||
return res
|
||||
}
|
||||
|
||||
// Request review from the PR author
|
||||
err = addReviewers(
|
||||
ctx,
|
||||
github,
|
||||
r.Owner,
|
||||
r.Repo,
|
||||
int(res.PullRequest.GetNumber()),
|
||||
[]string{pr.GetUser().GetLogin()},
|
||||
)
|
||||
if err != nil {
|
||||
res.Error = fmt.Errorf("requesting review from PR author on backport pull request %w", err)
|
||||
return res
|
||||
}
|
||||
|
||||
// Copy non-backport labels from the original PR to the backport PR
|
||||
labelsToAdd := filterNonBackportLabels(pr.Labels, r.BackportLabelPrefix)
|
||||
err = addLabelsToIssue(
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ importers:
|
|||
version: 3.0.0
|
||||
'@hashicorp/vault-client-typescript':
|
||||
specifier: github:hashicorp/vault-client-typescript
|
||||
version: https://codeload.github.com/hashicorp/vault-client-typescript/tar.gz/0ba8e35e7fcf5b93110bb7fbcc2608184fd5ae07
|
||||
version: https://codeload.github.com/hashicorp/vault-client-typescript/tar.gz/d0d038ea91aa92ecd0fd5d9e8f35b75a8c7e559c
|
||||
ember-auto-import:
|
||||
specifier: 2.10.0
|
||||
version: 2.10.0(@glint/template@1.7.3)(webpack@5.105.4)
|
||||
|
|
@ -1601,8 +1601,8 @@ packages:
|
|||
'@hashicorp/flight-icons@3.14.0':
|
||||
resolution: {integrity: sha512-nyLDApaZsAHpAf2sRNwYX1MnJQU9UI3euiwE6wHPl2l/+Yt8wba1oXkmWL/Ptc4QgJxxnRUUhf66jGcB/AIOyQ==}
|
||||
|
||||
'@hashicorp/vault-client-typescript@https://codeload.github.com/hashicorp/vault-client-typescript/tar.gz/0ba8e35e7fcf5b93110bb7fbcc2608184fd5ae07':
|
||||
resolution: {tarball: https://codeload.github.com/hashicorp/vault-client-typescript/tar.gz/0ba8e35e7fcf5b93110bb7fbcc2608184fd5ae07}
|
||||
'@hashicorp/vault-client-typescript@https://codeload.github.com/hashicorp/vault-client-typescript/tar.gz/d0d038ea91aa92ecd0fd5d9e8f35b75a8c7e559c':
|
||||
resolution: {tarball: https://codeload.github.com/hashicorp/vault-client-typescript/tar.gz/d0d038ea91aa92ecd0fd5d9e8f35b75a8c7e559c}
|
||||
version: 0.0.0
|
||||
|
||||
'@humanwhocodes/config-array@0.13.0':
|
||||
|
|
@ -7201,8 +7201,8 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
semver@7.8.0:
|
||||
resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==}
|
||||
semver@7.8.1:
|
||||
resolution: {integrity: sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
|
|
@ -11269,7 +11269,7 @@ snapshots:
|
|||
|
||||
'@hashicorp/flight-icons@3.14.0': {}
|
||||
|
||||
'@hashicorp/vault-client-typescript@https://codeload.github.com/hashicorp/vault-client-typescript/tar.gz/0ba8e35e7fcf5b93110bb7fbcc2608184fd5ae07': {}
|
||||
'@hashicorp/vault-client-typescript@https://codeload.github.com/hashicorp/vault-client-typescript/tar.gz/d0d038ea91aa92ecd0fd5d9e8f35b75a8c7e559c': {}
|
||||
|
||||
'@humanwhocodes/config-array@0.13.0':
|
||||
dependencies:
|
||||
|
|
@ -18467,7 +18467,7 @@ snapshots:
|
|||
|
||||
semver@7.7.4: {}
|
||||
|
||||
semver@7.8.0: {}
|
||||
semver@7.8.1: {}
|
||||
|
||||
send@0.19.0:
|
||||
dependencies:
|
||||
|
|
@ -19420,7 +19420,7 @@ snapshots:
|
|||
espree: 9.6.1
|
||||
esquery: 1.7.0
|
||||
lodash: 4.18.0
|
||||
semver: 7.8.0
|
||||
semver: 7.8.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue