Skip to content

Commit 5d36bcc

Browse files
committed
Merge remote-tracking branch 'origin' into fix/release-discussion-category
2 parents 7234007 + 6e14426 commit 5d36bcc

File tree

178 files changed

+5080
-1608
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

178 files changed

+5080
-1608
lines changed

.github/workflows/go.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ jobs:
1717
- name: Check out code
1818
uses: actions/checkout@v2
1919

20+
- name: Cache Go modules
21+
uses: actions/cache@v2
22+
with:
23+
path: ~/go
24+
key: ${{ runner.os }}-build-${{ hashFiles('go.mod') }}
25+
restore-keys: |
26+
${{ runner.os }}-build-
27+
${{ runner.os }}-
28+
2029
- name: Download dependencies
2130
run: go mod download
2231

.github/workflows/releases.yml

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ jobs:
2525
-q .body > CHANGELOG.md
2626
env:
2727
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
28+
- name: Install osslsigncode
29+
run: sudo apt-get install -y osslsigncode
30+
- name: Obtain signing cert
31+
run: |
32+
cert="$(mktemp -t cert.XXX)"
33+
base64 -d <<<"$CERT_CONTENTS" > "$cert"
34+
echo "CERT_FILE=$cert" >> $GITHUB_ENV
35+
env:
36+
CERT_CONTENTS: ${{ secrets.WINDOWS_CERT_PFX }}
2837
- name: Run GoReleaser
2938
uses: goreleaser/goreleaser-action@v2
3039
with:
@@ -33,6 +42,7 @@ jobs:
3342
env:
3443
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
3544
GORELEASER_CURRENT_TAG: ${{steps.changelog.outputs.tag-name}}
45+
CERT_PASSWORD: ${{secrets.WINDOWS_CERT_PASSWORD}}
3646
- name: Checkout documentation site
3747
uses: actions/checkout@v2
3848
with:
@@ -61,7 +71,6 @@ jobs:
6171
api-write --silent projects/columns/cards/$card/moves -f position=top -F column_id=$DONE_COLUMN
6272
done
6373
echo "moved ${#cards[@]} cards to the Done column"
64-
6574
- name: Install packaging dependencies
6675
run: sudo apt-get install -y rpm reprepro
6776
- name: Set up GPG
@@ -129,34 +138,33 @@ jobs:
129138
unzip -o *.zip && rm -v *.zip
130139
env:
131140
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
132-
- name: Install go-msi
133-
run: choco install -y "go-msi"
134141
- name: Prepare PATH
135-
shell: bash
136-
run: |
137-
echo "$WIX\\bin" >> $GITHUB_PATH
138-
echo "C:\\Program Files\\go-msi" >> $GITHUB_PATH
142+
id: setupmsbuild
143+
uses: microsoft/setup-msbuild@v1.0.3
139144
- name: Build MSI
140145
id: buildmsi
141146
shell: bash
142147
env:
143148
ZIP_FILE: ${{ steps.download_exe.outputs.zip }}
149+
MSBUILD_PATH: ${{ steps.setupmsbuild.outputs.msbuildPath }}
144150
run: |
145-
mkdir -p build
146-
msi="$(basename "$ZIP_FILE" ".zip").msi"
147-
printf "::set-output name=msi::%s\n" "$msi"
148-
go-msi make --msi "$PWD/$msi" --out "$PWD/build" --version "${GITHUB_REF#refs/tags/}"
151+
name="$(basename "$ZIP_FILE" ".zip")"
152+
version="$(echo -e ${GITHUB_REF#refs/tags/v} | sed s/-.*$//)"
153+
"${MSBUILD_PATH}\MSBuild.exe" ./build/windows/gh.wixproj -p:SourceDir="$PWD" -p:OutputPath="$PWD" -p:OutputName="$name" -p:ProductVersion="$version"
149154
- name: Obtain signing cert
150155
id: obtain_cert
156+
shell: bash
157+
run: |
158+
base64 -d <<<"$CERT_CONTENTS" > ./cert.pfx
159+
printf "::set-output name=cert-file::%s\n" ".\\cert.pfx"
151160
env:
152-
DESKTOP_CERT_TOKEN: ${{ secrets.DESKTOP_CERT_TOKEN }}
153-
run: .\script\setup-windows-certificate.ps1
161+
CERT_CONTENTS: ${{ secrets.WINDOWS_CERT_PFX }}
154162
- name: Sign MSI
155163
env:
156164
CERT_FILE: ${{ steps.obtain_cert.outputs.cert-file }}
157165
EXE_FILE: ${{ steps.buildmsi.outputs.msi }}
158-
GITHUB_CERT_PASSWORD: ${{ secrets.GITHUB_CERT_PASSWORD }}
159-
run: .\script\sign.ps1 -Certificate $env:CERT_FILE -Executable $env:EXE_FILE
166+
CERT_PASSWORD: ${{ secrets.WINDOWS_CERT_PASSWORD }}
167+
run: .\script\signtool sign /d "GitHub CLI" /f $env:CERT_FILE /p $env:CERT_PASSWORD /fd sha256 /tr http://timestamp.digicert.com /v $env:EXE_FILE
160168
- name: Upload MSI
161169
shell: bash
162170
run: |

.goreleaser.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ builds:
3232
id: windows
3333
goos: [windows]
3434
goarch: [386, amd64]
35+
hooks:
36+
post:
37+
- ./script/sign-windows-executable.sh '{{ .Path }}'
3538

3639
archives:
3740
- id: nix

api/client.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,22 @@ func ReplaceTripper(tr http.RoundTripper) ClientOption {
9898
}
9999
}
100100

101+
// ExtractHeader extracts a named header from any response received by this client and, if non-blank, saves
102+
// it to dest.
103+
func ExtractHeader(name string, dest *string) ClientOption {
104+
return func(tr http.RoundTripper) http.RoundTripper {
105+
return &funcTripper{roundTrip: func(req *http.Request) (*http.Response, error) {
106+
res, err := tr.RoundTrip(req)
107+
if err == nil {
108+
if value := res.Header.Get(name); value != "" {
109+
*dest = value
110+
}
111+
}
112+
return res, err
113+
}}
114+
}
115+
}
116+
101117
type funcTripper struct {
102118
roundTrip func(*http.Request) (*http.Response, error)
103119
}
@@ -310,6 +326,7 @@ func (c Client) REST(hostname string, method string, p string, body io.Reader, d
310326
if err != nil {
311327
return err
312328
}
329+
313330
err = json.Unmarshal(b, &data)
314331
if err != nil {
315332
return err

api/export_pr.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ func (pr *PullRequest) ExportData(fields []string) map[string]interface{} {
7575
data[f] = pr.ProjectCards.Nodes
7676
case "reviews":
7777
data[f] = pr.Reviews.Nodes
78+
case "latestReviews":
79+
data[f] = pr.LatestReviews.Nodes
7880
case "files":
7981
data[f] = pr.Files.Nodes
8082
case "reviewRequests":

api/queries_pr.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ type PullRequest struct {
6464

6565
BaseRef struct {
6666
BranchProtectionRule struct {
67-
RequiresStrictStatusChecks bool
67+
RequiresStrictStatusChecks bool
68+
RequiredApprovingReviewCount int
6869
}
6970
}
7071

@@ -79,18 +80,7 @@ type PullRequest struct {
7980
Commit struct {
8081
StatusCheckRollup struct {
8182
Contexts struct {
82-
Nodes []struct {
83-
TypeName string `json:"__typename"`
84-
Name string `json:"name"`
85-
Context string `json:"context,omitempty"`
86-
State string `json:"state,omitempty"`
87-
Status string `json:"status"`
88-
Conclusion string `json:"conclusion"`
89-
StartedAt time.Time `json:"startedAt"`
90-
CompletedAt time.Time `json:"completedAt"`
91-
DetailsURL string `json:"detailsUrl"`
92-
TargetURL string `json:"targetUrl,omitempty"`
93-
}
83+
Nodes []CheckContext
9484
PageInfo struct {
9585
HasNextPage bool
9686
EndCursor string
@@ -108,9 +98,23 @@ type PullRequest struct {
10898
Comments Comments
10999
ReactionGroups ReactionGroups
110100
Reviews PullRequestReviews
101+
LatestReviews PullRequestReviews
111102
ReviewRequests ReviewRequests
112103
}
113104

105+
type CheckContext struct {
106+
TypeName string `json:"__typename"`
107+
Name string `json:"name"`
108+
Context string `json:"context,omitempty"`
109+
State string `json:"state,omitempty"`
110+
Status string `json:"status"`
111+
Conclusion string `json:"conclusion"`
112+
StartedAt time.Time `json:"startedAt"`
113+
CompletedAt time.Time `json:"completedAt"`
114+
DetailsURL string `json:"detailsUrl"`
115+
TargetURL string `json:"targetUrl,omitempty"`
116+
}
117+
114118
type PRRepository struct {
115119
ID string `json:"id"`
116120
Name string `json:"name"`
@@ -405,6 +409,11 @@ func PullRequestStatus(client *Client, repo ghrepo.Interface, options StatusOpti
405409
}
406410
pullRequest(number: $number) {
407411
...prWithReviews
412+
baseRef {
413+
branchProtectionRule {
414+
requiredApprovingReviewCount
415+
}
416+
}
408417
}
409418
}
410419
`
@@ -519,7 +528,7 @@ func pullRequestFragment(httpClient *http.Client, hostname string) (string, erro
519528

520529
var reviewFields []string
521530
if prFeatures.HasReviewDecision {
522-
reviewFields = append(reviewFields, "reviewDecision")
531+
reviewFields = append(reviewFields, "reviewDecision", "latestReviews")
523532
}
524533

525534
fragments := fmt.Sprintf(`

api/queries_repo.go

Lines changed: 42 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"strings"
1212
"time"
1313

14+
"github.com/cli/cli/v2/internal/ghinstance"
15+
1416
"github.com/cli/cli/v2/internal/ghrepo"
1517
"github.com/shurcooL/githubv4"
1618
)
@@ -524,6 +526,37 @@ func ForkRepo(client *Client, repo ghrepo.Interface, org string) (*Repository, e
524526
}, nil
525527
}
526528

529+
// RenameRepo renames the repository on GitHub and returns the renamed repository
530+
func RenameRepo(client *Client, repo ghrepo.Interface, newRepoName string) (*Repository, error) {
531+
input := map[string]string{"name": newRepoName}
532+
body := &bytes.Buffer{}
533+
enc := json.NewEncoder(body)
534+
if err := enc.Encode(input); err != nil {
535+
return nil, err
536+
}
537+
538+
path := fmt.Sprintf("%srepos/%s",
539+
ghinstance.RESTPrefix(repo.RepoHost()),
540+
ghrepo.FullName(repo))
541+
542+
result := repositoryV3{}
543+
err := client.REST(repo.RepoHost(), "PATCH", path, body, &result)
544+
if err != nil {
545+
return nil, err
546+
}
547+
548+
return &Repository{
549+
ID: result.NodeID,
550+
Name: result.Name,
551+
CreatedAt: result.CreatedAt,
552+
Owner: RepositoryOwner{
553+
Login: result.Owner.Login,
554+
},
555+
ViewerPermission: "WRITE",
556+
hostname: repo.RepoHost(),
557+
}, nil
558+
}
559+
527560
func LastCommit(client *Client, repo ghrepo.Interface) (*Commit, error) {
528561
var responseData struct {
529562
Repository struct {
@@ -983,6 +1016,15 @@ func RepoAndOrgProjects(client *Client, repo ghrepo.Interface) ([]RepoProject, e
9831016
type RepoAssignee struct {
9841017
ID string
9851018
Login string
1019+
Name string
1020+
}
1021+
1022+
// DisplayName returns a formatted string that uses Login and Name to be displayed e.g. 'Login (Name)' or 'Login'
1023+
func (ra RepoAssignee) DisplayName() string {
1024+
if ra.Name != "" {
1025+
return fmt.Sprintf("%s (%s)", ra.Login, ra.Name)
1026+
}
1027+
return ra.Login
9861028
}
9871029

9881030
// RepoAssignableUsers fetches all the assignable users for a repository
@@ -1128,46 +1170,6 @@ func RepoMilestones(client *Client, repo ghrepo.Interface, state string) ([]Repo
11281170
return milestones, nil
11291171
}
11301172

1131-
func MilestoneByTitle(client *Client, repo ghrepo.Interface, state, title string) (*RepoMilestone, error) {
1132-
milestones, err := RepoMilestones(client, repo, state)
1133-
if err != nil {
1134-
return nil, err
1135-
}
1136-
1137-
for i := range milestones {
1138-
if strings.EqualFold(milestones[i].Title, title) {
1139-
return &milestones[i], nil
1140-
}
1141-
}
1142-
return nil, fmt.Errorf("no milestone found with title %q", title)
1143-
}
1144-
1145-
func MilestoneByNumber(client *Client, repo ghrepo.Interface, number int32) (*RepoMilestone, error) {
1146-
var query struct {
1147-
Repository struct {
1148-
Milestone *RepoMilestone `graphql:"milestone(number: $number)"`
1149-
} `graphql:"repository(owner: $owner, name: $name)"`
1150-
}
1151-
1152-
variables := map[string]interface{}{
1153-
"owner": githubv4.String(repo.RepoOwner()),
1154-
"name": githubv4.String(repo.RepoName()),
1155-
"number": githubv4.Int(number),
1156-
}
1157-
1158-
gql := graphQLClient(client.http, repo.RepoHost())
1159-
1160-
err := gql.QueryNamed(context.Background(), "RepositoryMilestoneByNumber", &query, variables)
1161-
if err != nil {
1162-
return nil, err
1163-
}
1164-
if query.Repository.Milestone == nil {
1165-
return nil, fmt.Errorf("no milestone found with number '%d'", number)
1166-
}
1167-
1168-
return query.Repository.Milestone, nil
1169-
}
1170-
11711173
func ProjectNamesToPaths(client *Client, repo ghrepo.Interface, projectNames []string) ([]string, error) {
11721174
var paths []string
11731175
projects, err := RepoAndOrgProjects(client, repo)

api/queries_repo_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,28 @@ func Test_RepoMilestones(t *testing.T) {
362362
}
363363
}
364364
}
365+
366+
func TestDisplayName(t *testing.T) {
367+
tests := []struct {
368+
name string
369+
assignee RepoAssignee
370+
want string
371+
}{
372+
{
373+
name: "assignee with name",
374+
assignee: RepoAssignee{"123", "octocat123", "Octavious Cath"},
375+
want: "octocat123 (Octavious Cath)",
376+
},
377+
{
378+
name: "assignee without name",
379+
assignee: RepoAssignee{"123", "octocat123", ""},
380+
want: "octocat123",
381+
},
382+
}
383+
for _, tt := range tests {
384+
actual := tt.assignee.DisplayName()
385+
if actual != tt.want {
386+
t.Errorf("display name was %s wanted %s", actual, tt.want)
387+
}
388+
}
389+
}

api/query_builder.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,18 @@ var prReviews = shortenQuery(`
8282
}
8383
`)
8484

85+
var prLatestReviews = shortenQuery(`
86+
latestReviews(first: 100) {
87+
nodes {
88+
author{login},
89+
authorAssociation,
90+
submittedAt,
91+
body,
92+
state
93+
}
94+
}
95+
`)
96+
8597
var prFiles = shortenQuery(`
8698
files(first: 100) {
8799
nodes {
@@ -180,6 +192,7 @@ var PullRequestFields = append(IssueFields,
180192
"headRepositoryOwner",
181193
"isCrossRepository",
182194
"isDraft",
195+
"latestReviews",
183196
"maintainerCanModify",
184197
"mergeable",
185198
"mergeCommit",
@@ -229,6 +242,8 @@ func PullRequestGraphQL(fields []string) string {
229242
q = append(q, prReviewRequests)
230243
case "reviews":
231244
q = append(q, prReviews)
245+
case "latestReviews":
246+
q = append(q, prLatestReviews)
232247
case "files":
233248
q = append(q, prFiles)
234249
case "commits":

0 commit comments

Comments
 (0)