From 5fc311374aa270c713593e4f808234d4b374a338 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Fri, 4 Oct 2024 10:08:48 -0700 Subject: [PATCH 01/53] Add handling of empty titles for Issues and PRs Currently, the prompter doesn't enforce the requirement of a title for PR and Issue creation. However, that creates the UX where a user can enter a blank title, spend time filling out a detailed body, then fail to create the issue or pr when the request is sent to the api because the title is blank. This attempts to handle that before sending a request to the api, enforcing that, when prompting, the title of an issue is not blank. --- pkg/cmd/pr/shared/survey.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pkg/cmd/pr/shared/survey.go b/pkg/cmd/pr/shared/survey.go index 5b8bde0eb..a059b288c 100644 --- a/pkg/cmd/pr/shared/survey.go +++ b/pkg/cmd/pr/shared/survey.go @@ -111,9 +111,16 @@ func BodySurvey(p Prompt, state *IssueMetadataState, templateContent string) err } func TitleSurvey(p Prompt, state *IssueMetadataState) error { - result, err := p.Input("Title", state.Title) - if err != nil { - return err + var err error + result := "" + for result == "" { + result, err = p.Input("Title (required)", state.Title) + if err != nil { + return err + } + if result == "" { + fmt.Println("X Title cannot be blank.") + } } if result != state.Title { From be3b6cbd8dd2fd99315404b909fd958307c42c8f Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Tue, 8 Oct 2024 16:03:14 -0700 Subject: [PATCH 02/53] Make the X in the error message red and print with io writer --- pkg/cmd/issue/create/create.go | 2 +- pkg/cmd/pr/create/create.go | 2 +- pkg/cmd/pr/shared/survey.go | 7 +++++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/issue/create/create.go b/pkg/cmd/issue/create/create.go index 82d4ab133..f51cde4c9 100644 --- a/pkg/cmd/issue/create/create.go +++ b/pkg/cmd/issue/create/create.go @@ -222,7 +222,7 @@ func createRun(opts *CreateOptions) (err error) { defer prShared.PreserveInput(opts.IO, &tb, &err)() if opts.Title == "" { - err = prShared.TitleSurvey(opts.Prompter, &tb) + err = prShared.TitleSurvey(opts.Prompter, opts.IO, &tb) if err != nil { return } diff --git a/pkg/cmd/pr/create/create.go b/pkg/cmd/pr/create/create.go index 7e893395c..1242af2c5 100644 --- a/pkg/cmd/pr/create/create.go +++ b/pkg/cmd/pr/create/create.go @@ -379,7 +379,7 @@ func createRun(opts *CreateOptions) (err error) { } else { if !opts.TitleProvided { - err = shared.TitleSurvey(opts.Prompter, state) + err = shared.TitleSurvey(opts.Prompter, opts.IO, state) if err != nil { return } diff --git a/pkg/cmd/pr/shared/survey.go b/pkg/cmd/pr/shared/survey.go index a059b288c..2ee343bfb 100644 --- a/pkg/cmd/pr/shared/survey.go +++ b/pkg/cmd/pr/shared/survey.go @@ -110,7 +110,7 @@ func BodySurvey(p Prompt, state *IssueMetadataState, templateContent string) err return nil } -func TitleSurvey(p Prompt, state *IssueMetadataState) error { +func TitleSurvey(p Prompt, io *iostreams.IOStreams, state *IssueMetadataState) error { var err error result := "" for result == "" { @@ -119,7 +119,10 @@ func TitleSurvey(p Prompt, state *IssueMetadataState) error { return err } if result == "" { - fmt.Println("X Title cannot be blank.") + colorizeRed := io.ColorScheme().ColorFromString("red") + msg := fmt.Sprintf("%s Title cannot be blank.", colorizeRed("X")) + // For some reason, only Fprintln and Println work here. I can't use Fprintf or Printf to eliminate the line above + fmt.Fprintln(io.ErrOut, msg) } } From da945314fd3179e3eb4cfab3d1681a210969f90a Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Tue, 8 Oct 2024 16:11:05 -0700 Subject: [PATCH 03/53] Fix failing test for pr and issue create --- pkg/cmd/issue/create/create_test.go | 4 ++-- pkg/cmd/pr/create/create_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/issue/create/create_test.go b/pkg/cmd/issue/create/create_test.go index b95b5ef66..8e49700a0 100644 --- a/pkg/cmd/issue/create/create_test.go +++ b/pkg/cmd/issue/create/create_test.go @@ -611,7 +611,7 @@ func TestIssueCreate_recover(t *testing.T) { pm := &prompter.PrompterMock{} pm.InputFunc = func(p, d string) (string, error) { - if p == "Title" { + if p == "Title (required)" { return d, nil } else { return "", prompter.NoSuchPromptErr(p) @@ -736,7 +736,7 @@ func TestIssueCreate_continueInBrowser(t *testing.T) { pm := &prompter.PrompterMock{} pm.InputFunc = func(p, d string) (string, error) { - if p == "Title" { + if p == "Title (required)" { return "hello", nil } else { return "", prompter.NoSuchPromptErr(p) diff --git a/pkg/cmd/pr/create/create_test.go b/pkg/cmd/pr/create/create_test.go index cba552101..81684ff00 100644 --- a/pkg/cmd/pr/create/create_test.go +++ b/pkg/cmd/pr/create/create_test.go @@ -1210,7 +1210,7 @@ func Test_createRun(t *testing.T) { }, promptStubs: func(pm *prompter.PrompterMock) { pm.InputFunc = func(p, d string) (string, error) { - if p == "Title" { + if p == "Title (required)" { return d, nil } else { return "", prompter.NoSuchPromptErr(p) @@ -1316,7 +1316,7 @@ func Test_createRun(t *testing.T) { } pm.InputFunc = func(p, d string) (string, error) { - if p == "Title" { + if p == "Title (required)" { return d, nil } else if p == "Body" { return d, nil From dcbd1b728cd87523768807262b44f7cc94bbb582 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Tue, 8 Oct 2024 16:32:50 -0700 Subject: [PATCH 04/53] Add test coverage for TitleSurvey change --- pkg/cmd/pr/shared/survey_test.go | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/pkg/cmd/pr/shared/survey_test.go b/pkg/cmd/pr/shared/survey_test.go index 8df492785..0e62e0e5a 100644 --- a/pkg/cmd/pr/shared/survey_test.go +++ b/pkg/cmd/pr/shared/survey_test.go @@ -158,3 +158,44 @@ type testEditor struct { func (e testEditor) Edit(filename, text string) (string, error) { return e.edit(text) } + +func TestTitleSurvey(t *testing.T) { + tests := []struct { + name string + prompterMockInputs []string + expectedTitle string + expectStderr bool + }{ + { + name: "title provided", + prompterMockInputs: []string{"title"}, + expectedTitle: "title", + }, + { + name: "first input empty", + prompterMockInputs: []string{"", "title"}, + expectedTitle: "title", + expectStderr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + io, _, _, stderr := iostreams.Test() + pm := prompter.NewMockPrompter(t) + for _, input := range tt.prompterMockInputs { + pm.RegisterInput("Title (required)", func(string, string) (string, error) { + return input, nil + }) + } + + state := &IssueMetadataState{} + err := TitleSurvey(pm, io, state) + + assert.NoError(t, err) + assert.Equal(t, tt.expectedTitle, state.Title) + if tt.expectStderr { + assert.Equal(t, "X Title cannot be blank.\n", stderr.String()) + } + }) + } +} From aaea0166e2824f12454c8f7d785bd7481eddebe1 Mon Sep 17 00:00:00 2001 From: Phill MV Date: Wed, 9 Oct 2024 16:51:00 -0400 Subject: [PATCH 05/53] If provided with zero attestations to verify, the LiveSigstoreVerifier.Verify func should return an error. --- pkg/cmd/attestation/verification/sigstore.go | 22 ++++++++++++++----- .../verification/sigstore_integration_test.go | 15 +++++++++++++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/pkg/cmd/attestation/verification/sigstore.go b/pkg/cmd/attestation/verification/sigstore.go index ca4015db2..e237a3eb9 100644 --- a/pkg/cmd/attestation/verification/sigstore.go +++ b/pkg/cmd/attestation/verification/sigstore.go @@ -4,6 +4,7 @@ import ( "bufio" "bytes" "crypto/x509" + "errors" "fmt" "os" @@ -48,6 +49,8 @@ type LiveSigstoreVerifier struct { config SigstoreConfig } +var ErrNoAttestationsVerified = errors.New("no attestations were verified") + // NewLiveSigstoreVerifier creates a new LiveSigstoreVerifier struct // that is used to verify artifacts and attestations against the // Public Good, GitHub, or a custom trusted root. @@ -170,18 +173,20 @@ func getLowestCertInChain(ca *root.CertificateAuthority) (*x509.Certificate, err } func (v *LiveSigstoreVerifier) Verify(attestations []*api.Attestation, policy verify.PolicyBuilder) *SigstoreResults { - // initialize the processing results before attempting to verify + // initialize the processing apResults before attempting to verify // with multiple verifiers - results := make([]*AttestationProcessingResult, len(attestations)) + apResults := make([]*AttestationProcessingResult, len(attestations)) for i, att := range attestations { apr := &AttestationProcessingResult{ Attestation: att, } - results[i] = apr + apResults[i] = apr } + var atLeastOneVerified bool + totalAttestations := len(attestations) - for i, apr := range results { + for i, apr := range apResults { v.config.Logger.VerbosePrintf("Verifying attestation %d/%d against the configured Sigstore trust roots\n", i+1, totalAttestations) // determine which verifier should attempt verification against the bundle @@ -212,10 +217,15 @@ func (v *LiveSigstoreVerifier) Verify(attestations []*api.Attestation, policy ve "SUCCESS - attestation signature verified with \"%s\"\n", issuer, )) apr.VerificationResult = result + atLeastOneVerified = true } - return &SigstoreResults{ - VerifyResults: results, + if atLeastOneVerified { + return &SigstoreResults{ + VerifyResults: apResults, + } + } else { + return &SigstoreResults{Error: ErrNoAttestationsVerified} } } diff --git a/pkg/cmd/attestation/verification/sigstore_integration_test.go b/pkg/cmd/attestation/verification/sigstore_integration_test.go index 97b44581e..1d3ec2d75 100644 --- a/pkg/cmd/attestation/verification/sigstore_integration_test.go +++ b/pkg/cmd/attestation/verification/sigstore_integration_test.go @@ -85,6 +85,21 @@ func TestLiveSigstoreVerifier(t *testing.T) { require.Len(t, res.VerifyResults, 0) require.ErrorContains(t, res.Error, "unsupported bundle version") }) + + t.Run("with no attestations", func(t *testing.T) { + attestations := []*api.Attestation{} + require.Len(t, attestations, 0) + + verifier := NewLiveSigstoreVerifier(SigstoreConfig{ + Logger: io.NewTestHandler(), + TrustedRoot: test.NormalizeRelativePath("../test/data/trusted_root.json"), + }) + + res := verifier.Verify(attestations, publicGoodPolicy(t)) + require.Len(t, res.VerifyResults, 0) + require.NotNil(t, res.Error) + }) + } func publicGoodPolicy(t *testing.T) verify.PolicyBuilder { From 28c2308458261f3961d25bde6bd7091062c41825 Mon Sep 17 00:00:00 2001 From: Phill MV Date: Thu, 10 Oct 2024 11:22:22 -0400 Subject: [PATCH 06/53] While we're at it, let's ensure VerifyCertExtensions can't be tricked the same way. --- pkg/cmd/attestation/verification/extensions.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/attestation/verification/extensions.go b/pkg/cmd/attestation/verification/extensions.go index 2ffb11a9d..94ba88208 100644 --- a/pkg/cmd/attestation/verification/extensions.go +++ b/pkg/cmd/attestation/verification/extensions.go @@ -16,12 +16,19 @@ func VerifyCertExtensions(results []*AttestationProcessingResult, tenant, owner, return errors.New("no attestations proccessing results") } + var atLeastOneVerified bool for _, attestation := range results { if err := verifyCertExtensions(attestation, tenant, owner, repo, issuer); err != nil { return err } + atLeastOneVerified = true + } + + if atLeastOneVerified { + return nil + } else { + return ErrNoAttestationsVerified } - return nil } func verifyCertExtensions(attestation *AttestationProcessingResult, tenant, owner, repo, issuer string) error { From d709dd5b597421216f7ea9bbd6906d9b6072c870 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:22:07 +0000 Subject: [PATCH 07/53] build(deps): bump github.com/gabriel-vasile/mimetype from 1.4.5 to 1.4.6 Bumps [github.com/gabriel-vasile/mimetype](https://github.com/gabriel-vasile/mimetype) from 1.4.5 to 1.4.6. - [Release notes](https://github.com/gabriel-vasile/mimetype/releases) - [Commits](https://github.com/gabriel-vasile/mimetype/compare/v1.4.5...v1.4.6) --- updated-dependencies: - dependency-name: github.com/gabriel-vasile/mimetype dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index e638459fa..d9675cba2 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.5 github.com/creack/pty v1.1.23 github.com/distribution/reference v0.5.0 - github.com/gabriel-vasile/mimetype v1.4.5 + github.com/gabriel-vasile/mimetype v1.4.6 github.com/gdamore/tcell/v2 v2.5.4 github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.20.2 @@ -43,10 +43,10 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 github.com/zalando/go-keyring v0.2.5 - golang.org/x/crypto v0.27.0 + golang.org/x/crypto v0.28.0 golang.org/x/sync v0.8.0 - golang.org/x/term v0.24.0 - golang.org/x/text v0.18.0 + golang.org/x/term v0.25.0 + golang.org/x/text v0.19.0 google.golang.org/grpc v1.64.1 google.golang.org/protobuf v1.34.2 gopkg.in/h2non/gock.v1 v1.1.2 @@ -158,7 +158,7 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect golang.org/x/mod v0.20.0 // indirect - golang.org/x/net v0.27.0 // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/sys v0.26.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 // indirect diff --git a/go.sum b/go.sum index d1a85b60e..9d0e0e264 100644 --- a/go.sum +++ b/go.sum @@ -147,8 +147,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= -github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= +github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc= +github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.5.4 h1:TGU4tSjD3sCL788vFNeJnTdzpNKIw1H5dgLnJRQVv/k= @@ -486,8 +486,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -496,8 +496,8 @@ golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -519,15 +519,15 @@ golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From c3ffdc90c8819e1e7c70fb66ab4a5bb20d5fe871 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 11:01:09 -0600 Subject: [PATCH 08/53] implement base workflow list acceptance test --- acceptance/acceptance_test.go | 29 +++++++++++ .../testdata/workflow/workflow-list.txtar | 52 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 acceptance/testdata/workflow/workflow-list.txtar diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index cbd59b761..e390f2247 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -6,8 +6,10 @@ import ( "fmt" "os" "path" + "strconv" "strings" "testing" + "time" "math/rand" @@ -35,6 +37,16 @@ func TestPullRequests(t *testing.T) { testscript.Run(t, testScriptParamsFor(tsEnv, "pr")) } +func TestWorkflows(t *testing.T) { + var tsEnv testScriptEnv + if err := tsEnv.fromEnv(); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + + testscript.Run(t, testScriptParamsFor(tsEnv, "workflow")) +} + func testScriptParamsFor(tsEnv testScriptEnv, command string) testscript.Params { var files []string if tsEnv.script != "" { @@ -119,6 +131,23 @@ func sharedCmds(tsEnv testScriptEnv) map[string]func(ts *testscript.TestScript, ts.Setenv(args[0], strings.TrimRight(ts.ReadFile("stdout"), "\n")) }, + "sleep": func(ts *testscript.TestScript, neg bool, args []string) { + if neg { + ts.Fatalf("unsupported: ! sleep") + } + if len(args) != 1 { + ts.Fatalf("usage: sleep seconds") + } + + // sleep for the given number of seconds + seconds, err := strconv.Atoi(args[0]) + if err != nil { + ts.Fatalf("invalid number of seconds: %v", err) + } + + d := time.Duration(seconds) * time.Second + time.Sleep(d) + }, } } diff --git a/acceptance/testdata/workflow/workflow-list.txtar b/acceptance/testdata/workflow/workflow-list.txtar new file mode 100644 index 000000000..8cd211de0 --- /dev/null +++ b/acceptance/testdata/workflow/workflow-list.txtar @@ -0,0 +1,52 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +-- workflow.yml -- +# This is a basic workflow to help you get started with Actions + +name: Test Workflow Name + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v4 + + # Runs a single command using the runners shell + - name: Run a one-line script + run: sleep 10 From 5f919bc5b0f931d19c26ff9d8b648a23468c0358 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 11:01:21 -0600 Subject: [PATCH 09/53] implement workflow enable/disable acceptance test --- .../workflow/workflow-enable-disable.txtar | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 acceptance/testdata/workflow/workflow-enable-disable.txtar diff --git a/acceptance/testdata/workflow/workflow-enable-disable.txtar b/acceptance/testdata/workflow/workflow-enable-disable.txtar new file mode 100644 index 000000000..c248c1cad --- /dev/null +++ b/acceptance/testdata/workflow/workflow-enable-disable.txtar @@ -0,0 +1,71 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# disable the workflow +exec gh workflow disable 'Test Workflow Name' + +# Check the workflow is indeed disabled +# Disabled workflows are hidden by default. +exec gh workflow list +stdout '' + +# Check that the listing shows it is disabled +exec gh workflow list --all +stdout 'Test\s+Workflow\s+Name\s+disabled_manually\s+\d+' + +# enable the workflow +exec gh workflow enable 'Test Workflow Name' + +# Check the workflow is indeed enabled +exec gh workflow list +stdout 'Test Workflow Name' + +-- workflow.yml -- +# This is a basic workflow to help you get started with Actions + +name: Test Workflow Name + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v4 + + # Runs a single command using the runners shell + - name: Run a one-line script + run: sleep 10 From 0b1d6923e1f8d660482c838bbfed7e1233309926 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 11:37:06 -0600 Subject: [PATCH 10/53] Create workflow-view.txtar --- .../testdata/workflow/workflow-view.txtar | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 acceptance/testdata/workflow/workflow-view.txtar diff --git a/acceptance/testdata/workflow/workflow-view.txtar b/acceptance/testdata/workflow/workflow-view.txtar new file mode 100644 index 000000000..0783e7fac --- /dev/null +++ b/acceptance/testdata/workflow/workflow-view.txtar @@ -0,0 +1,52 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow view 'Test Workflow Name' +stdout 'Test Workflow Name - workflow.yml' + +-- workflow.yml -- +# This is a basic workflow to help you get started with Actions + +name: Test Workflow Name + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v4 + + # Runs a single command using the runners shell + - name: Run a one-line script + run: sleep 10 From 3737f10246ac9be516f9059a4eb308bbaa91447a Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 11:37:11 -0600 Subject: [PATCH 11/53] Create workflow-run.txtar --- .../testdata/workflow/workflow-run.txtar | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 acceptance/testdata/workflow/workflow-run.txtar diff --git a/acceptance/testdata/workflow/workflow-run.txtar b/acceptance/testdata/workflow/workflow-run.txtar new file mode 100644 index 000000000..7e9a823ee --- /dev/null +++ b/acceptance/testdata/workflow/workflow-run.txtar @@ -0,0 +1,62 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 5 + +# Check the workflow run exists +exec gh run list +stdout 'Test Workflow Name' + +-- workflow.yml -- +# This is a basic workflow to help you get started with Actions + +name: Test Workflow Name + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v4 + + # Runs a single command using the runners shell + - name: Run a one-line script + run: echo Hello, world! From 446ffede1281359c0e4edc143a80321332c28dda Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 11:37:14 -0600 Subject: [PATCH 12/53] Create run-cancel.txtar --- acceptance/testdata/workflow/run-cancel.txtar | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 acceptance/testdata/workflow/run-cancel.txtar diff --git a/acceptance/testdata/workflow/run-cancel.txtar b/acceptance/testdata/workflow/run-cancel.txtar new file mode 100644 index 000000000..f06912c90 --- /dev/null +++ b/acceptance/testdata/workflow/run-cancel.txtar @@ -0,0 +1,73 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 5 + +# Get the run ID we want to cancel +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# cancel the workflow run +exec gh run cancel $RUN_ID +stdout '✓ Request to cancel workflow [0-9]+ submitted.' + +# It takes some time for a workflow run to be cancelled +sleep 5 + +# Check the workflow run is cancelled +exec gh run list --json conclusion --jq '.[0].conclusion' +stdout 'cancelled' + +-- workflow.yml -- +# This is a basic workflow to help you get started with Actions + +name: Test Workflow Name + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v4 + + # Runs a single command using the runners shell + - name: Run a one-line script + run: sleep 30 From 4df2e7be634cf2eb7f7d63b61351d68afc1c6c07 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Tue, 15 Oct 2024 12:16:20 -0700 Subject: [PATCH 13/53] Remove comment --- pkg/cmd/pr/shared/survey.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/cmd/pr/shared/survey.go b/pkg/cmd/pr/shared/survey.go index 2ee343bfb..3d53be4c7 100644 --- a/pkg/cmd/pr/shared/survey.go +++ b/pkg/cmd/pr/shared/survey.go @@ -121,7 +121,6 @@ func TitleSurvey(p Prompt, io *iostreams.IOStreams, state *IssueMetadataState) e if result == "" { colorizeRed := io.ColorScheme().ColorFromString("red") msg := fmt.Sprintf("%s Title cannot be blank.", colorizeRed("X")) - // For some reason, only Fprintln and Println work here. I can't use Fprintf or Printf to eliminate the line above fmt.Fprintln(io.ErrOut, msg) } } From 3f080e0948dc8d5e88a3e8b3104ab10486348534 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:19:44 -0600 Subject: [PATCH 14/53] Create run-delete.txtar --- acceptance/testdata/workflow/run-delete.txtar | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 acceptance/testdata/workflow/run-delete.txtar diff --git a/acceptance/testdata/workflow/run-delete.txtar b/acceptance/testdata/workflow/run-delete.txtar new file mode 100644 index 000000000..16dc224fb --- /dev/null +++ b/acceptance/testdata/workflow/run-delete.txtar @@ -0,0 +1,74 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 5 + +# Get the run ID we want to watch & delete +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# Wait for workflow to complete +exec gh run watch $RUN_ID --exit-status + +# Delete the workflow run +exec gh run delete $RUN_ID +stdout '✓ Request to delete workflow submitted.' + +# It takes some time for a workflow run to be deleted +sleep 5 + +# Check the workflow run is cancelled +exec gh run list +stdout '' + +-- workflow.yml -- +# This is a basic workflow to help you get started with Actions + +name: Test Workflow Name + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + + # Runs a single command using the runners shell + - name: Run a one-line script + run: echo Hello, world! From 3d3e061d06b6384efdc6189aad649b3acca00d35 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:19:47 -0600 Subject: [PATCH 15/53] Create run-download.txtar --- .../testdata/workflow/run-download.txtar | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 acceptance/testdata/workflow/run-download.txtar diff --git a/acceptance/testdata/workflow/run-download.txtar b/acceptance/testdata/workflow/run-download.txtar new file mode 100644 index 000000000..2aa3cae64 --- /dev/null +++ b/acceptance/testdata/workflow/run-download.txtar @@ -0,0 +1,72 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 5 + +# Get the run ID we want to watch +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# Wait for workflow to complete +exec gh run watch $RUN_ID --exit-status + +# Download the artifact +exec gh run download $RUN_ID +stdout '' + +# Check if we downloaded the artifact +exists ./my-artifact/world.txt + +-- workflow.yml -- +# This is a basic workflow to help you get started with Actions + +name: Test Workflow Name + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - run: mkdir -p path/to/artifact + - run: echo hello > world.txt + - uses: actions/upload-artifact@v4 + with: + name: my-artifact + path: world.txt \ No newline at end of file From 745863b3656a5f106dffcc11f9e5835fe7851362 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:19:49 -0600 Subject: [PATCH 16/53] Create run-rerun.txtar --- acceptance/testdata/workflow/run-rerun.txtar | 79 ++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 acceptance/testdata/workflow/run-rerun.txtar diff --git a/acceptance/testdata/workflow/run-rerun.txtar b/acceptance/testdata/workflow/run-rerun.txtar new file mode 100644 index 000000000..e5b895454 --- /dev/null +++ b/acceptance/testdata/workflow/run-rerun.txtar @@ -0,0 +1,79 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 5 + +# Get the run ID we want to rerun +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# Wait for workflow to complete +exec gh run watch $RUN_ID --exit-status + +# Get the run ID we want to rerun +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# Rerun the workflow run +# There's some inconsistency here compared to `run delete` and other `run` +# commands because run rerun doesn't return output in non-tty. +exec gh run rerun $RUN_ID +stdout '' + +# It takes some time for a workflow run to register +sleep 5 + +# Wait for workflow to complete +exec gh run watch $RUN_ID --exit-status + +-- workflow.yml -- +# This is a basic workflow to help you get started with Actions + +name: Test Workflow Name + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + + # Runs a single command using the runners shell + - name: Run a one-line script + run: echo Hello, world! From 682b75fb4e91bc90da966d74543acb1f36fcfb8d Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:19:52 -0600 Subject: [PATCH 17/53] Create run-view.txtar --- acceptance/testdata/workflow/run-view.txtar | 66 +++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 acceptance/testdata/workflow/run-view.txtar diff --git a/acceptance/testdata/workflow/run-view.txtar b/acceptance/testdata/workflow/run-view.txtar new file mode 100644 index 000000000..c3ace4c4f --- /dev/null +++ b/acceptance/testdata/workflow/run-view.txtar @@ -0,0 +1,66 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 5 + +# Get the run ID we want to view +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# Wait for workflow to complete +exec gh run watch $RUN_ID --exit-status + +# View the workflow run +exec gh run view $RUN_ID + +-- workflow.yml -- +# This is a basic workflow to help you get started with Actions + +name: Test Workflow Name + +# Controls when the workflow will run +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + build: + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + + # Runs a single command using the runners shell + - name: Run a one-line script + run: sleep 10 From 924d81a34bed6f34fbbe134a1f2f5b644fe0715b Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:59:19 -0600 Subject: [PATCH 18/53] Create cache-list-delete.txtar --- .../testdata/workflow/cache-list-delete.txtar | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 acceptance/testdata/workflow/cache-list-delete.txtar diff --git a/acceptance/testdata/workflow/cache-list-delete.txtar b/acceptance/testdata/workflow/cache-list-delete.txtar new file mode 100644 index 000000000..30ce78bd0 --- /dev/null +++ b/acceptance/testdata/workflow/cache-list-delete.txtar @@ -0,0 +1,70 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# commit the workflow file +cd $SCRIPT_NAME-$RANDOM_STRING +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 5 + +# Get the run ID we want to watch +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# Wait for workflow to complete +exec gh run watch $RUN_ID --exit-status + +# List the cache +exec gh cache list +stdout 'Linux-values' + +# Delete the cache +exec gh cache delete 'Linux-values' +stdout '' + +-- workflow.yml -- +name: Test Workflow Name + +on: workflow_dispatch + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Cache values + id: cache-values + uses: actions/cache@v4 + with: + path: values.txt + key: ${{ runner.os }}-values + + - name: Generate values file + if: steps.cache-values.outputs.cache-hit != 'true' + run: echo "values" > values.txt \ No newline at end of file From 8d626312a487c5f7efa9acc4cf708c9200c967de Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:59:21 -0600 Subject: [PATCH 19/53] Update run-rerun.txtar --- acceptance/testdata/workflow/run-rerun.txtar | 2 -- 1 file changed, 2 deletions(-) diff --git a/acceptance/testdata/workflow/run-rerun.txtar b/acceptance/testdata/workflow/run-rerun.txtar index e5b895454..1448dec4b 100644 --- a/acceptance/testdata/workflow/run-rerun.txtar +++ b/acceptance/testdata/workflow/run-rerun.txtar @@ -43,8 +43,6 @@ exec gh run list --json databaseId --jq '.[0].databaseId' stdout2env RUN_ID # Rerun the workflow run -# There's some inconsistency here compared to `run delete` and other `run` -# commands because run rerun doesn't return output in non-tty. exec gh run rerun $RUN_ID stdout '' From 4ce82361422807f0a3f066f93b89ddfeb11dba0c Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:09:47 -0600 Subject: [PATCH 20/53] sleep 10s before checking for workflow run --- acceptance/testdata/workflow/cache-list-delete.txtar | 2 +- acceptance/testdata/workflow/run-cancel.txtar | 2 +- acceptance/testdata/workflow/run-delete.txtar | 2 +- acceptance/testdata/workflow/run-download.txtar | 2 +- acceptance/testdata/workflow/run-rerun.txtar | 8 ++------ acceptance/testdata/workflow/run-view.txtar | 2 +- acceptance/testdata/workflow/workflow-run.txtar | 2 +- 7 files changed, 8 insertions(+), 12 deletions(-) diff --git a/acceptance/testdata/workflow/cache-list-delete.txtar b/acceptance/testdata/workflow/cache-list-delete.txtar index 30ce78bd0..aa1dc91a7 100644 --- a/acceptance/testdata/workflow/cache-list-delete.txtar +++ b/acceptance/testdata/workflow/cache-list-delete.txtar @@ -29,7 +29,7 @@ stdout 'Test Workflow Name' exec gh workflow run 'Test Workflow Name' # It takes some time for a workflow run to register -sleep 5 +sleep 10 # Get the run ID we want to watch exec gh run list --json databaseId --jq '.[0].databaseId' diff --git a/acceptance/testdata/workflow/run-cancel.txtar b/acceptance/testdata/workflow/run-cancel.txtar index f06912c90..2f1170bbc 100644 --- a/acceptance/testdata/workflow/run-cancel.txtar +++ b/acceptance/testdata/workflow/run-cancel.txtar @@ -29,7 +29,7 @@ stdout 'Test Workflow Name' exec gh workflow run 'Test Workflow Name' # It takes some time for a workflow run to register -sleep 5 +sleep 10 # Get the run ID we want to cancel exec gh run list --json databaseId --jq '.[0].databaseId' diff --git a/acceptance/testdata/workflow/run-delete.txtar b/acceptance/testdata/workflow/run-delete.txtar index 16dc224fb..45b11f2d1 100644 --- a/acceptance/testdata/workflow/run-delete.txtar +++ b/acceptance/testdata/workflow/run-delete.txtar @@ -29,7 +29,7 @@ stdout 'Test Workflow Name' exec gh workflow run 'Test Workflow Name' # It takes some time for a workflow run to register -sleep 5 +sleep 10 # Get the run ID we want to watch & delete exec gh run list --json databaseId --jq '.[0].databaseId' diff --git a/acceptance/testdata/workflow/run-download.txtar b/acceptance/testdata/workflow/run-download.txtar index 2aa3cae64..a8faaacec 100644 --- a/acceptance/testdata/workflow/run-download.txtar +++ b/acceptance/testdata/workflow/run-download.txtar @@ -29,7 +29,7 @@ stdout 'Test Workflow Name' exec gh workflow run 'Test Workflow Name' # It takes some time for a workflow run to register -sleep 5 +sleep 10 # Get the run ID we want to watch exec gh run list --json databaseId --jq '.[0].databaseId' diff --git a/acceptance/testdata/workflow/run-rerun.txtar b/acceptance/testdata/workflow/run-rerun.txtar index 1448dec4b..273a4adea 100644 --- a/acceptance/testdata/workflow/run-rerun.txtar +++ b/acceptance/testdata/workflow/run-rerun.txtar @@ -29,7 +29,7 @@ stdout 'Test Workflow Name' exec gh workflow run 'Test Workflow Name' # It takes some time for a workflow run to register -sleep 5 +sleep 10 # Get the run ID we want to rerun exec gh run list --json databaseId --jq '.[0].databaseId' @@ -38,16 +38,12 @@ stdout2env RUN_ID # Wait for workflow to complete exec gh run watch $RUN_ID --exit-status -# Get the run ID we want to rerun -exec gh run list --json databaseId --jq '.[0].databaseId' -stdout2env RUN_ID - # Rerun the workflow run exec gh run rerun $RUN_ID stdout '' # It takes some time for a workflow run to register -sleep 5 +sleep 10 # Wait for workflow to complete exec gh run watch $RUN_ID --exit-status diff --git a/acceptance/testdata/workflow/run-view.txtar b/acceptance/testdata/workflow/run-view.txtar index c3ace4c4f..bc739e580 100644 --- a/acceptance/testdata/workflow/run-view.txtar +++ b/acceptance/testdata/workflow/run-view.txtar @@ -29,7 +29,7 @@ stdout 'Test Workflow Name' exec gh workflow run 'Test Workflow Name' # It takes some time for a workflow run to register -sleep 5 +sleep 10 # Get the run ID we want to view exec gh run list --json databaseId --jq '.[0].databaseId' diff --git a/acceptance/testdata/workflow/workflow-run.txtar b/acceptance/testdata/workflow/workflow-run.txtar index 7e9a823ee..010189c01 100644 --- a/acceptance/testdata/workflow/workflow-run.txtar +++ b/acceptance/testdata/workflow/workflow-run.txtar @@ -29,7 +29,7 @@ stdout 'Test Workflow Name' exec gh workflow run 'Test Workflow Name' # It takes some time for a workflow run to register -sleep 5 +sleep 10 # Check the workflow run exists exec gh run list From fdfd4b30bb6f4627f782cc5555e046bad1beece0 Mon Sep 17 00:00:00 2001 From: Yukai Chou Date: Thu, 17 Oct 2024 01:12:21 +0800 Subject: [PATCH 21/53] Rewrite a sentence in CONTRIBUTING.md --- .github/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 35b211236..9a0acb58e 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -6,7 +6,7 @@ We accept pull requests for bug fixes and features where we've discussed the app Please do: -* Check existing issues to verify that an existing [bug][bug issues] or [feature request][feature request issues] issue does not already exist for the same problem or feature. +* Check issues to verify that a [bug][bug issues] or [feature request][feature request issues] issue does not already exist for the same problem or feature. * Open an issue if things aren't working as expected. * Open an issue to propose a significant change. * Open an issue to propose a design for an issue labelled [`needs-design` and `help wanted`][needs design and help wanted], following the [proposing a design guidelines](#proposing-a-design) instructions below. From 86b4bb99561857310bf0bc3238d928a1e0af5d60 Mon Sep 17 00:00:00 2001 From: Andy Feller Date: Wed, 16 Oct 2024 19:38:10 -0400 Subject: [PATCH 22/53] Include startedAt, completedAt in run steps data This commit expands the `Step` structure used with GitHub Actions workflow runs to include fields indicating when steps start and complete. This information is already provided by the GitHub API, so this only involves expanding the structure, fields exported, and the associated tests. In the future, I could see `gh` including the duration calculation which is used when viewing workflow or workflow run. --- pkg/cmd/run/shared/shared.go | 32 ++++++++++++++++---------- pkg/cmd/run/shared/shared_test.go | 38 +++++++++++++++++++------------ 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/pkg/cmd/run/shared/shared.go b/pkg/cmd/run/shared/shared.go index e5f09dec9..90ab5a7fe 100644 --- a/pkg/cmd/run/shared/shared.go +++ b/pkg/cmd/run/shared/shared.go @@ -180,16 +180,22 @@ func (r *Run) ExportData(fields []string) map[string]interface{} { for _, j := range r.Jobs { steps := make([]interface{}, 0, len(j.Steps)) for _, s := range j.Steps { + var stepCompletedAt time.Time + if !s.CompletedAt.IsZero() { + stepCompletedAt = s.CompletedAt + } steps = append(steps, map[string]interface{}{ - "name": s.Name, - "status": s.Status, - "conclusion": s.Conclusion, - "number": s.Number, + "name": s.Name, + "status": s.Status, + "conclusion": s.Conclusion, + "number": s.Number, + "startedAt": s.StartedAt, + "completedAt": stepCompletedAt, }) } - var completedAt time.Time + var jobCompletedAt time.Time if !j.CompletedAt.IsZero() { - completedAt = j.CompletedAt + jobCompletedAt = j.CompletedAt } jobs = append(jobs, map[string]interface{}{ "databaseId": j.ID, @@ -198,7 +204,7 @@ func (r *Run) ExportData(fields []string) map[string]interface{} { "name": j.Name, "steps": steps, "startedAt": j.StartedAt, - "completedAt": completedAt, + "completedAt": jobCompletedAt, "url": j.URL, }) } @@ -225,11 +231,13 @@ type Job struct { } type Step struct { - Name string - Status Status - Conclusion Conclusion - Number int - Log *zip.File + Name string + Status Status + Conclusion Conclusion + Number int + StartedAt time.Time `json:"started_at"` + CompletedAt time.Time `json:"completed_at"` + Log *zip.File } type Steps []Step diff --git a/pkg/cmd/run/shared/shared_test.go b/pkg/cmd/run/shared/shared_test.go index 15663cd0a..752ba2fc4 100644 --- a/pkg/cmd/run/shared/shared_test.go +++ b/pkg/cmd/run/shared/shared_test.go @@ -110,8 +110,12 @@ func TestRun_Duration(t *testing.T) { func TestRunExportData(t *testing.T) { oldestStartedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:20:13Z") + oldestStepStartedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:20:15Z") + oldestStepCompletedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:21:10Z") oldestCompletedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:21:16Z") newestStartedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:20:55Z") + newestStepStartedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:21:01Z") + newestStepCompletedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:23:10Z") newestCompletedAt, _ := time.Parse(time.RFC3339, "2022-07-20T11:23:16Z") tests := []struct { @@ -132,10 +136,12 @@ func TestRunExportData(t *testing.T) { Name: "macos", Steps: []Step{ { - Name: "Checkout", - Status: "completed", - Conclusion: "success", - Number: 1, + Name: "Checkout", + Status: "completed", + Conclusion: "success", + Number: 1, + StartedAt: oldestStepStartedAt, + CompletedAt: oldestStepCompletedAt, }, }, StartedAt: oldestStartedAt, @@ -144,7 +150,7 @@ func TestRunExportData(t *testing.T) { }, }, }, - output: `{"jobs":[{"completedAt":"2022-07-20T11:21:16Z","conclusion":"success","databaseId":123456,"name":"macos","startedAt":"2022-07-20T11:20:13Z","status":"completed","steps":[{"conclusion":"success","name":"Checkout","number":1,"status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/123456"}]}`, + output: `{"jobs":[{"completedAt":"2022-07-20T11:21:16Z","conclusion":"success","databaseId":123456,"name":"macos","startedAt":"2022-07-20T11:20:13Z","status":"completed","steps":[{"completedAt":"2022-07-20T11:21:10Z","conclusion":"success","name":"Checkout","number":1,"startedAt":"2022-07-20T11:20:15Z","status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/123456"}]}`, }, { name: "exports workflow run's multiple jobs", @@ -158,10 +164,12 @@ func TestRunExportData(t *testing.T) { Name: "macos", Steps: []Step{ { - Name: "Checkout", - Status: "completed", - Conclusion: "success", - Number: 1, + Name: "Checkout", + Status: "completed", + Conclusion: "success", + Number: 1, + StartedAt: oldestStepStartedAt, + CompletedAt: oldestStepCompletedAt, }, }, StartedAt: oldestStartedAt, @@ -175,10 +183,12 @@ func TestRunExportData(t *testing.T) { Name: "windows", Steps: []Step{ { - Name: "Checkout", - Status: "completed", - Conclusion: "error", - Number: 2, + Name: "Checkout", + Status: "completed", + Conclusion: "error", + Number: 2, + StartedAt: newestStepStartedAt, + CompletedAt: newestStepCompletedAt, }, }, StartedAt: newestStartedAt, @@ -187,7 +197,7 @@ func TestRunExportData(t *testing.T) { }, }, }, - output: `{"jobs":[{"completedAt":"2022-07-20T11:21:16Z","conclusion":"success","databaseId":123456,"name":"macos","startedAt":"2022-07-20T11:20:13Z","status":"completed","steps":[{"conclusion":"success","name":"Checkout","number":1,"status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/123456"},{"completedAt":"2022-07-20T11:23:16Z","conclusion":"error","databaseId":234567,"name":"windows","startedAt":"2022-07-20T11:20:55Z","status":"completed","steps":[{"conclusion":"error","name":"Checkout","number":2,"status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/234567"}]}`, + output: `{"jobs":[{"completedAt":"2022-07-20T11:21:16Z","conclusion":"success","databaseId":123456,"name":"macos","startedAt":"2022-07-20T11:20:13Z","status":"completed","steps":[{"completedAt":"2022-07-20T11:21:10Z","conclusion":"success","name":"Checkout","number":1,"startedAt":"2022-07-20T11:20:15Z","status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/123456"},{"completedAt":"2022-07-20T11:23:16Z","conclusion":"error","databaseId":234567,"name":"windows","startedAt":"2022-07-20T11:20:55Z","status":"completed","steps":[{"completedAt":"2022-07-20T11:23:10Z","conclusion":"error","name":"Checkout","number":2,"startedAt":"2022-07-20T11:21:01Z","status":"completed"}],"url":"https://example.com/OWNER/REPO/actions/runs/234567"}]}`, }, { name: "exports workflow run with attempt count", From 8f567e2791abe3cf6bc750b383753184ad527a16 Mon Sep 17 00:00:00 2001 From: William Martin Date: Thu, 17 Oct 2024 14:13:50 +0200 Subject: [PATCH 23/53] Watch for run to end for cancel Acceptance test --- acceptance/testdata/workflow/run-cancel.txtar | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acceptance/testdata/workflow/run-cancel.txtar b/acceptance/testdata/workflow/run-cancel.txtar index 2f1170bbc..08d8d519a 100644 --- a/acceptance/testdata/workflow/run-cancel.txtar +++ b/acceptance/testdata/workflow/run-cancel.txtar @@ -39,8 +39,8 @@ stdout2env RUN_ID exec gh run cancel $RUN_ID stdout '✓ Request to cancel workflow [0-9]+ submitted.' -# It takes some time for a workflow run to be cancelled -sleep 5 +# Wait for workflow to complete +exec gh run watch $RUN_ID # Check the workflow run is cancelled exec gh run list --json conclusion --jq '.[0].conclusion' From 93081c9e65acaf6c56009a642a03259d48a34a91 Mon Sep 17 00:00:00 2001 From: William Martin Date: Thu, 17 Oct 2024 14:25:02 +0200 Subject: [PATCH 24/53] Use regex assert for enable disable workflow Acceptance test --- acceptance/testdata/workflow/workflow-enable-disable.txtar | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/acceptance/testdata/workflow/workflow-enable-disable.txtar b/acceptance/testdata/workflow/workflow-enable-disable.txtar index c248c1cad..c18ae7dc7 100644 --- a/acceptance/testdata/workflow/workflow-enable-disable.txtar +++ b/acceptance/testdata/workflow/workflow-enable-disable.txtar @@ -28,11 +28,6 @@ stdout 'Test Workflow Name' # disable the workflow exec gh workflow disable 'Test Workflow Name' -# Check the workflow is indeed disabled -# Disabled workflows are hidden by default. -exec gh workflow list -stdout '' - # Check that the listing shows it is disabled exec gh workflow list --all stdout 'Test\s+Workflow\s+Name\s+disabled_manually\s+\d+' @@ -42,7 +37,7 @@ exec gh workflow enable 'Test Workflow Name' # Check the workflow is indeed enabled exec gh workflow list -stdout 'Test Workflow Name' +stdout 'Test\s+Workflow\s+Name\s+active\s+\d+' -- workflow.yml -- # This is a basic workflow to help you get started with Actions From 0f62ec20e261796d314586e45446ee2736ac200c Mon Sep 17 00:00:00 2001 From: William Martin Date: Thu, 17 Oct 2024 15:06:45 +0200 Subject: [PATCH 25/53] Adjust sleeps to echos in Acceptance workflows --- acceptance/testdata/workflow/run-view.txtar | 2 +- acceptance/testdata/workflow/workflow-enable-disable.txtar | 2 +- acceptance/testdata/workflow/workflow-list.txtar | 2 +- acceptance/testdata/workflow/workflow-view.txtar | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/acceptance/testdata/workflow/run-view.txtar b/acceptance/testdata/workflow/run-view.txtar index bc739e580..25f12c3a5 100644 --- a/acceptance/testdata/workflow/run-view.txtar +++ b/acceptance/testdata/workflow/run-view.txtar @@ -63,4 +63,4 @@ jobs: # Runs a single command using the runners shell - name: Run a one-line script - run: sleep 10 + run: echo Hello, world! diff --git a/acceptance/testdata/workflow/workflow-enable-disable.txtar b/acceptance/testdata/workflow/workflow-enable-disable.txtar index c18ae7dc7..f0b58116f 100644 --- a/acceptance/testdata/workflow/workflow-enable-disable.txtar +++ b/acceptance/testdata/workflow/workflow-enable-disable.txtar @@ -63,4 +63,4 @@ jobs: # Runs a single command using the runners shell - name: Run a one-line script - run: sleep 10 + run: echo Hello, world! diff --git a/acceptance/testdata/workflow/workflow-list.txtar b/acceptance/testdata/workflow/workflow-list.txtar index 8cd211de0..ad0d87c88 100644 --- a/acceptance/testdata/workflow/workflow-list.txtar +++ b/acceptance/testdata/workflow/workflow-list.txtar @@ -49,4 +49,4 @@ jobs: # Runs a single command using the runners shell - name: Run a one-line script - run: sleep 10 + run: echo Hello, world! diff --git a/acceptance/testdata/workflow/workflow-view.txtar b/acceptance/testdata/workflow/workflow-view.txtar index 0783e7fac..d3bc3d252 100644 --- a/acceptance/testdata/workflow/workflow-view.txtar +++ b/acceptance/testdata/workflow/workflow-view.txtar @@ -49,4 +49,4 @@ jobs: # Runs a single command using the runners shell - name: Run a one-line script - run: sleep 10 + run: echo Hello, world! From 07ea43ae5ab6b987ad0123b8d7f53553e1addc3f Mon Sep 17 00:00:00 2001 From: William Martin Date: Thu, 17 Oct 2024 15:09:27 +0200 Subject: [PATCH 26/53] Remove empty stdout checks --- acceptance/testdata/workflow/cache-list-delete.txtar | 3 +-- acceptance/testdata/workflow/run-delete.txtar | 2 +- acceptance/testdata/workflow/run-download.txtar | 3 +-- acceptance/testdata/workflow/run-rerun.txtar | 1 - 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/acceptance/testdata/workflow/cache-list-delete.txtar b/acceptance/testdata/workflow/cache-list-delete.txtar index aa1dc91a7..6a99f4bc2 100644 --- a/acceptance/testdata/workflow/cache-list-delete.txtar +++ b/acceptance/testdata/workflow/cache-list-delete.txtar @@ -44,7 +44,6 @@ stdout 'Linux-values' # Delete the cache exec gh cache delete 'Linux-values' -stdout '' -- workflow.yml -- name: Test Workflow Name @@ -67,4 +66,4 @@ jobs: - name: Generate values file if: steps.cache-values.outputs.cache-hit != 'true' - run: echo "values" > values.txt \ No newline at end of file + run: echo "values" > values.txt diff --git a/acceptance/testdata/workflow/run-delete.txtar b/acceptance/testdata/workflow/run-delete.txtar index 45b11f2d1..72d098740 100644 --- a/acceptance/testdata/workflow/run-delete.txtar +++ b/acceptance/testdata/workflow/run-delete.txtar @@ -45,7 +45,7 @@ stdout '✓ Request to delete workflow submitted.' # It takes some time for a workflow run to be deleted sleep 5 -# Check the workflow run is cancelled +# Check the workflow run is cancelled, which is implied by an empty list exec gh run list stdout '' diff --git a/acceptance/testdata/workflow/run-download.txtar b/acceptance/testdata/workflow/run-download.txtar index a8faaacec..dc0446598 100644 --- a/acceptance/testdata/workflow/run-download.txtar +++ b/acceptance/testdata/workflow/run-download.txtar @@ -40,7 +40,6 @@ exec gh run watch $RUN_ID --exit-status # Download the artifact exec gh run download $RUN_ID -stdout '' # Check if we downloaded the artifact exists ./my-artifact/world.txt @@ -69,4 +68,4 @@ jobs: - uses: actions/upload-artifact@v4 with: name: my-artifact - path: world.txt \ No newline at end of file + path: world.txt diff --git a/acceptance/testdata/workflow/run-rerun.txtar b/acceptance/testdata/workflow/run-rerun.txtar index 273a4adea..446aabbc4 100644 --- a/acceptance/testdata/workflow/run-rerun.txtar +++ b/acceptance/testdata/workflow/run-rerun.txtar @@ -40,7 +40,6 @@ exec gh run watch $RUN_ID --exit-status # Rerun the workflow run exec gh run rerun $RUN_ID -stdout '' # It takes some time for a workflow run to register sleep 10 From dc3e805078d6c043a2bccff29a8b3aca8ebc507e Mon Sep 17 00:00:00 2001 From: William Martin Date: Thu, 17 Oct 2024 15:11:45 +0200 Subject: [PATCH 27/53] Remove unnecesary mkdir from download Acceptance test --- acceptance/testdata/workflow/run-download.txtar | 1 - 1 file changed, 1 deletion(-) diff --git a/acceptance/testdata/workflow/run-download.txtar b/acceptance/testdata/workflow/run-download.txtar index dc0446598..653fdbef5 100644 --- a/acceptance/testdata/workflow/run-download.txtar +++ b/acceptance/testdata/workflow/run-download.txtar @@ -63,7 +63,6 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - - run: mkdir -p path/to/artifact - run: echo hello > world.txt - uses: actions/upload-artifact@v4 with: From 06c20f3a8b00916631a6eeb1bc23b1f2b795b0d1 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:31:20 -0600 Subject: [PATCH 28/53] Implement basic API acceptance test --- acceptance/acceptance_test.go | 9 +++++++++ acceptance/testdata/api/basic-graphql.txtar | 3 +++ acceptance/testdata/api/basic-rest.txtar | 3 +++ 3 files changed, 15 insertions(+) create mode 100644 acceptance/testdata/api/basic-graphql.txtar create mode 100644 acceptance/testdata/api/basic-rest.txtar diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 0c98271ca..3040ce9b2 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -55,6 +55,15 @@ func TestWorkflows(t *testing.T) { testscript.Run(t, testScriptParamsFor(tsEnv, "workflow")) } +func TestAPI(t *testing.T) { + var tsEnv testScriptEnv + if err := tsEnv.fromEnv(); err != nil { + t.Fatal(err) + } + + testscript.Run(t, testScriptParamsFor(tsEnv, "api")) +} + func testScriptParamsFor(tsEnv testScriptEnv, command string) testscript.Params { var files []string if tsEnv.script != "" { diff --git a/acceptance/testdata/api/basic-graphql.txtar b/acceptance/testdata/api/basic-graphql.txtar new file mode 100644 index 000000000..15c16c49c --- /dev/null +++ b/acceptance/testdata/api/basic-graphql.txtar @@ -0,0 +1,3 @@ +# Basic graphql request +exec gh api graphql -f query='query { viewer { login } }' +stdout '"login":' \ No newline at end of file diff --git a/acceptance/testdata/api/basic-rest.txtar b/acceptance/testdata/api/basic-rest.txtar new file mode 100644 index 000000000..58d3b7570 --- /dev/null +++ b/acceptance/testdata/api/basic-rest.txtar @@ -0,0 +1,3 @@ +# Basic REST request +exec gh api /user +stdout '"login":' \ No newline at end of file From a009933a166b022613e1f98c8951bcd3e7ec96b4 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:03:50 -0600 Subject: [PATCH 29/53] Add acceptance tests for `release` commands --- acceptance/acceptance_test.go | 12 +++++++-- acceptance/testdata/release/create.txtar | 12 +++++++++ acceptance/testdata/release/list.txtar | 16 ++++++++++++ .../testdata/release/upload-download.txtar | 25 +++++++++++++++++++ acceptance/testdata/release/view.txtar | 16 ++++++++++++ 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 acceptance/testdata/release/create.txtar create mode 100644 acceptance/testdata/release/list.txtar create mode 100644 acceptance/testdata/release/upload-download.txtar create mode 100644 acceptance/testdata/release/view.txtar diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 3040ce9b2..51e96778a 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -48,8 +48,7 @@ func TestIssues(t *testing.T) { func TestWorkflows(t *testing.T) { var tsEnv testScriptEnv if err := tsEnv.fromEnv(); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) + t.Fatal(err) } testscript.Run(t, testScriptParamsFor(tsEnv, "workflow")) @@ -64,6 +63,15 @@ func TestAPI(t *testing.T) { testscript.Run(t, testScriptParamsFor(tsEnv, "api")) } +func TestReleases(t *testing.T) { + var tsEnv testScriptEnv + if err := tsEnv.fromEnv(); err != nil { + t.Fatal(err) + } + + testscript.Run(t, testScriptParamsFor(tsEnv, "release")) +} + func testScriptParamsFor(tsEnv testScriptEnv, command string) testscript.Params { var files []string if tsEnv.script != "" { diff --git a/acceptance/testdata/release/create.txtar b/acceptance/testdata/release/create.txtar new file mode 100644 index 000000000..3bdafe769 --- /dev/null +++ b/acceptance/testdata/release/create.txtar @@ -0,0 +1,12 @@ +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Create a release in the repo +cd $SCRIPT_NAME-$RANDOM_STRING +exec gh release create v1.2.3 --notes 'awesome release' --latest diff --git a/acceptance/testdata/release/list.txtar b/acceptance/testdata/release/list.txtar new file mode 100644 index 000000000..844b25daa --- /dev/null +++ b/acceptance/testdata/release/list.txtar @@ -0,0 +1,16 @@ +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Create a release in the repo +cd $SCRIPT_NAME-$RANDOM_STRING +exec gh release create v1.2.3 --notes 'awesome release' --latest + +# List the releases +exec gh release list +stdout 'v1.2.3' \ No newline at end of file diff --git a/acceptance/testdata/release/upload-download.txtar b/acceptance/testdata/release/upload-download.txtar new file mode 100644 index 000000000..92bfa4c71 --- /dev/null +++ b/acceptance/testdata/release/upload-download.txtar @@ -0,0 +1,25 @@ +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Create a release in the repo +cd $SCRIPT_NAME-$RANDOM_STRING +exec gh release create v1.2.3 --notes 'awesome release' --latest + +# Upload an asset to the release +exec gh release upload v1.2.3 ../asset.txt +stdout '' + +# Download the asset from the release +exec gh release download v1.2.3 +exists asset.txt +exec gh release download v1.2.3 --archive=zip +exists $SCRIPT_NAME-$RANDOM_STRING-1.2.3.zip + +-- asset.txt -- +Hello, world! \ No newline at end of file diff --git a/acceptance/testdata/release/view.txtar b/acceptance/testdata/release/view.txtar new file mode 100644 index 000000000..a7138812a --- /dev/null +++ b/acceptance/testdata/release/view.txtar @@ -0,0 +1,16 @@ +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Create a release in the repo +cd $SCRIPT_NAME-$RANDOM_STRING +exec gh release create v1.2.3 --notes 'awesome release' --latest + +# View the release +exec gh release view v1.2.3 +stdout 'v1.2.3' \ No newline at end of file From 473faea5739a7b8dfd39740d74c0b83780c18c05 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Thu, 17 Oct 2024 07:43:21 -0600 Subject: [PATCH 30/53] Rename test files --- .../testdata/release/{create.txtar => release-create.txtar} | 0 acceptance/testdata/release/{list.txtar => release-list.txtar} | 0 .../{upload-download.txtar => release-upload-download.txtar} | 0 acceptance/testdata/release/{view.txtar => release-view.txtar} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename acceptance/testdata/release/{create.txtar => release-create.txtar} (100%) rename acceptance/testdata/release/{list.txtar => release-list.txtar} (100%) rename acceptance/testdata/release/{upload-download.txtar => release-upload-download.txtar} (100%) rename acceptance/testdata/release/{view.txtar => release-view.txtar} (100%) diff --git a/acceptance/testdata/release/create.txtar b/acceptance/testdata/release/release-create.txtar similarity index 100% rename from acceptance/testdata/release/create.txtar rename to acceptance/testdata/release/release-create.txtar diff --git a/acceptance/testdata/release/list.txtar b/acceptance/testdata/release/release-list.txtar similarity index 100% rename from acceptance/testdata/release/list.txtar rename to acceptance/testdata/release/release-list.txtar diff --git a/acceptance/testdata/release/upload-download.txtar b/acceptance/testdata/release/release-upload-download.txtar similarity index 100% rename from acceptance/testdata/release/upload-download.txtar rename to acceptance/testdata/release/release-upload-download.txtar diff --git a/acceptance/testdata/release/view.txtar b/acceptance/testdata/release/release-view.txtar similarity index 100% rename from acceptance/testdata/release/view.txtar rename to acceptance/testdata/release/release-view.txtar From 24fc2db39590bf92e0ff6df85d8609e33ec48c6f Mon Sep 17 00:00:00 2001 From: William Martin Date: Thu, 17 Oct 2024 15:54:50 +0200 Subject: [PATCH 31/53] Remove stdout assertion from release --- acceptance/testdata/release/release-upload-download.txtar | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/acceptance/testdata/release/release-upload-download.txtar b/acceptance/testdata/release/release-upload-download.txtar index 92bfa4c71..e19bc06d7 100644 --- a/acceptance/testdata/release/release-upload-download.txtar +++ b/acceptance/testdata/release/release-upload-download.txtar @@ -13,13 +13,14 @@ exec gh release create v1.2.3 --notes 'awesome release' --latest # Upload an asset to the release exec gh release upload v1.2.3 ../asset.txt -stdout '' # Download the asset from the release exec gh release download v1.2.3 exists asset.txt + +# Download the asset in archive form exec gh release download v1.2.3 --archive=zip exists $SCRIPT_NAME-$RANDOM_STRING-1.2.3.zip -- asset.txt -- -Hello, world! \ No newline at end of file +Hello, world! From 13ab02729bd1b38c12d65199bbe57a6528bd2b99 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 14:40:17 -0700 Subject: [PATCH 32/53] Clean up Title Survey empty title message code --- pkg/cmd/pr/shared/survey.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/cmd/pr/shared/survey.go b/pkg/cmd/pr/shared/survey.go index 3d53be4c7..ce38535d9 100644 --- a/pkg/cmd/pr/shared/survey.go +++ b/pkg/cmd/pr/shared/survey.go @@ -119,9 +119,7 @@ func TitleSurvey(p Prompt, io *iostreams.IOStreams, state *IssueMetadataState) e return err } if result == "" { - colorizeRed := io.ColorScheme().ColorFromString("red") - msg := fmt.Sprintf("%s Title cannot be blank.", colorizeRed("X")) - fmt.Fprintln(io.ErrOut, msg) + fmt.Fprintf(io.ErrOut, "%s Title cannot be blank\n", io.ColorScheme().FailureIcon()) } } From 14acbe00a93106cccb70cfd3c5fb290618d21866 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 14:45:35 -0700 Subject: [PATCH 33/53] Remove . from test case for TestTitleSurvey --- pkg/cmd/pr/shared/survey_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/pr/shared/survey_test.go b/pkg/cmd/pr/shared/survey_test.go index 0e62e0e5a..d74696460 100644 --- a/pkg/cmd/pr/shared/survey_test.go +++ b/pkg/cmd/pr/shared/survey_test.go @@ -194,7 +194,7 @@ func TestTitleSurvey(t *testing.T) { assert.NoError(t, err) assert.Equal(t, tt.expectedTitle, state.Title) if tt.expectStderr { - assert.Equal(t, "X Title cannot be blank.\n", stderr.String()) + assert.Equal(t, "X Title cannot be blank\n", stderr.String()) } }) } From b361cf4495230fb9f348622b59551ab22be286c3 Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:17:34 -0600 Subject: [PATCH 34/53] Implement acceptance tests for search commands --- acceptance/acceptance_test.go | 9 +++++++++ .../testdata/search/search-issues.txtar | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 acceptance/testdata/search/search-issues.txtar diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 51e96778a..750dadd76 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -72,6 +72,15 @@ func TestReleases(t *testing.T) { testscript.Run(t, testScriptParamsFor(tsEnv, "release")) } +func TestSearches(t *testing.T) { + var tsEnv testScriptEnv + if err := tsEnv.fromEnv(); err != nil { + t.Fatal(err) + } + + testscript.Run(t, testScriptParamsFor(tsEnv, "search")) +} + func testScriptParamsFor(tsEnv testScriptEnv, command string) testscript.Params { var files []string if tsEnv.script != "" { diff --git a/acceptance/testdata/search/search-issues.txtar b/acceptance/testdata/search/search-issues.txtar new file mode 100644 index 000000000..e41bc1eb6 --- /dev/null +++ b/acceptance/testdata/search/search-issues.txtar @@ -0,0 +1,19 @@ +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Create an issue in the repo +cd $SCRIPT_NAME-$RANDOM_STRING +exec gh issue create --title 'Feature Request' --body 'Feature Body $RANDOM_STRING' + +# It takes some time for the issue to be created and indexed +sleep 5 + +# Search for the issue +exec gh search issues 'Feature Body $RANDOM_STRING' -R $ORG/$SCRIPT_NAME-$RANDOM_STRING +stdout 'Feature Request' \ No newline at end of file From 18428671c3795504d15d8fa01199db595c2d3c0e Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Wed, 16 Oct 2024 15:14:18 -0700 Subject: [PATCH 35/53] Added test function for repos and repo-create test --- acceptance/acceptance_test.go | 8 ++++++++ acceptance/testdata/repos/repo-create-view.txtar | 12 ++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 acceptance/testdata/repos/repo-create-view.txtar diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 51e96778a..366d88cf4 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -72,6 +72,14 @@ func TestReleases(t *testing.T) { testscript.Run(t, testScriptParamsFor(tsEnv, "release")) } +func TestRepos(t *testing.T) { + var tsEnv testScriptEnv + if err := tsEnv.fromEnv(); err != nil { + t.Fatal(err) + } + testscript.Run(t, testScriptParamsFor(tsEnv, "repos")) +} + func testScriptParamsFor(tsEnv testScriptEnv, command string) testscript.Params { var files []string if tsEnv.script != "" { diff --git a/acceptance/testdata/repos/repo-create-view.txtar b/acceptance/testdata/repos/repo-create-view.txtar new file mode 100644 index 000000000..b5b85f593 --- /dev/null +++ b/acceptance/testdata/repos/repo-create-view.txtar @@ -0,0 +1,12 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Check that the repo exists +exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json name --jq '.name' +stdout $SCRIPT_NAME-$RANDOM_STRING \ No newline at end of file From 83cbdc4f3686cbfd1500ce71820d2e23997bcdee Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Wed, 16 Oct 2024 15:28:38 -0700 Subject: [PATCH 36/53] Added acceptance test for repo-delete --- acceptance/testdata/repos/repo-delete.txtar | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 acceptance/testdata/repos/repo-delete.txtar diff --git a/acceptance/testdata/repos/repo-delete.txtar b/acceptance/testdata/repos/repo-delete.txtar new file mode 100644 index 000000000..855473ae9 --- /dev/null +++ b/acceptance/testdata/repos/repo-delete.txtar @@ -0,0 +1,16 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Check that the repo exists +exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json name --jq '.name' +stdout $SCRIPT_NAME-$RANDOM_STRING + +# Delete the repo +exec gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Ensure that the repo was deleted +! exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json name --jq '.name' +stderr 'Could not resolve to a Repository with the name' \ No newline at end of file From 60e20ee5312b4caa9ce3e98b633bf974b949b863 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 08:51:51 -0700 Subject: [PATCH 37/53] Add acceptance test for repo-clone --- acceptance/testdata/repos/repo-clone.txtar | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 acceptance/testdata/repos/repo-clone.txtar diff --git a/acceptance/testdata/repos/repo-clone.txtar b/acceptance/testdata/repos/repo-clone.txtar new file mode 100644 index 000000000..f0bad8e01 --- /dev/null +++ b/acceptance/testdata/repos/repo-clone.txtar @@ -0,0 +1,15 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Ensure the repo was cloned +exec ls $SCRIPT_NAME-$RANDOM_STRING +stdout README.md \ No newline at end of file From 0c632d7c4eada9577449921c87c2cb7c340b9071 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 09:43:50 -0700 Subject: [PATCH 38/53] Acceptance testing for repo-archive and repo-unarchive --- .../repos/repo-archive-unarchive.txtar | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 acceptance/testdata/repos/repo-archive-unarchive.txtar diff --git a/acceptance/testdata/repos/repo-archive-unarchive.txtar b/acceptance/testdata/repos/repo-archive-unarchive.txtar new file mode 100644 index 000000000..d72b36906 --- /dev/null +++ b/acceptance/testdata/repos/repo-archive-unarchive.txtar @@ -0,0 +1,26 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Check that the repo exists and isn't archived +exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=isArchived --jq='.isArchived' +stdout false + +# Archive the repo +exec gh repo archive $ORG/$SCRIPT_NAME-$RANDOM_STRING --yes + +# Check that the repo is archived +exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=isArchived --jq='.isArchived' +stdout true + +# Unarchive the repo +exec gh repo unarchive $ORG/$SCRIPT_NAME-$RANDOM_STRING --yes + +# Check that the repo is unarchived +exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=isArchived --jq='.isArchived' +stdout false \ No newline at end of file From fb6f7733c4974524b25d6b7d66075e0d002a8a8c Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 09:58:59 -0700 Subject: [PATCH 39/53] Add acceptance tests for repo-list and repo-rename --- .../testdata/repos/repo-list-rename.txtar | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 acceptance/testdata/repos/repo-list-rename.txtar diff --git a/acceptance/testdata/repos/repo-list-rename.txtar b/acceptance/testdata/repos/repo-list-rename.txtar new file mode 100644 index 000000000..e758ac7fd --- /dev/null +++ b/acceptance/testdata/repos/repo-list-rename.txtar @@ -0,0 +1,24 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# List the repos and check for the new repo +exec gh repo list $ORG --json name --jq '.[].name' +stdout $SCRIPT_NAME-$RANDOM_STRING + +# Rename the repo +exec gh repo rename $SCRIPT_NAME-$RANDOM_STRING-renamed --repo=$ORG/$SCRIPT_NAME-$RANDOM_STRING --yes + +# List the repos and check for the renamed repo +exec gh repo list $ORG --json name --jq '.[].name' +stdout $SCRIPT_NAME-$RANDOM_STRING-renamed + +# Delete the renamed repo +exec gh repo delete $ORG/$SCRIPT_NAME-$RANDOM_STRING-renamed --yes + +# List the repos and check for the deleted repo +exec gh repo list $ORG --json name --jq '.[].name' +! stdout $SCRIPT_NAME-$RANDOM_STRING-renamed + From c572edbfd797780426def51559b3e0fece1ff59e Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 10:08:14 -0700 Subject: [PATCH 40/53] Add acceptance test for repo-edit --- acceptance/testdata/repos/repo-edit.txtar | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 acceptance/testdata/repos/repo-edit.txtar diff --git a/acceptance/testdata/repos/repo-edit.txtar b/acceptance/testdata/repos/repo-edit.txtar new file mode 100644 index 000000000..c8e293cc0 --- /dev/null +++ b/acceptance/testdata/repos/repo-edit.txtar @@ -0,0 +1,19 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Check that the repo description is empty +exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json description --jq '.description' +stdout '' + +# Edit the repo description +exec gh repo edit $ORG/$SCRIPT_NAME-$RANDOM_STRING --description 'newDescription' + +# Check that the repo description is updated +exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json description --jq '.description' +stdout 'newDescription' \ No newline at end of file From 750813135635b79c99ac292414e22f7d56cb7bb0 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 10:27:20 -0700 Subject: [PATCH 41/53] Add acceptance test for repo-set-default --- .../testdata/repos/repo-set-default.txtar | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 acceptance/testdata/repos/repo-set-default.txtar diff --git a/acceptance/testdata/repos/repo-set-default.txtar b/acceptance/testdata/repos/repo-set-default.txtar new file mode 100644 index 000000000..f8c0e68c5 --- /dev/null +++ b/acceptance/testdata/repos/repo-set-default.txtar @@ -0,0 +1,23 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Clone the repo +exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING +cd $SCRIPT_NAME-$RANDOM_STRING + +# Ensure that no default is set +exec gh repo set-default --view +stderr 'no default repository has been set; use `gh repo set-default` to select one' + +# Set the default +exec gh repo set-default $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Check that the default is set +exec gh repo set-default --view +stdout $ORG/$SCRIPT_NAME-$RANDOM_STRING \ No newline at end of file From 96fa8534daa9832b34fa42d432e66298e2fd62a4 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 10:55:28 -0700 Subject: [PATCH 42/53] Add acceptance tests for repo-fork and repo-sync --- .../testdata/repos/repo-fork-sync.txtar | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 acceptance/testdata/repos/repo-fork-sync.txtar diff --git a/acceptance/testdata/repos/repo-fork-sync.txtar b/acceptance/testdata/repos/repo-fork-sync.txtar new file mode 100644 index 000000000..73beb39f1 --- /dev/null +++ b/acceptance/testdata/repos/repo-fork-sync.txtar @@ -0,0 +1,44 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create and clone a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private --clone + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# Fork and clone the repo +exec gh repo fork $ORG/$SCRIPT_NAME-$RANDOM_STRING --org $ORG --fork-name $SCRIPT_NAME-$RANDOM_STRING-fork --clone + +# Defer fork cleanup +defer gh repo delete $ORG/$SCRIPT_NAME-$RANDOM_STRING-fork --yes + +# Sleep so that the BE has time to sync +sleep 5 + +# Check that the repo was forked +exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING-fork --json='isFork' --jq='.isFork' +stdout true + +# Modify original repo +cd $SCRIPT_NAME-$RANDOM_STRING +mv ../asset.txt asset.txt +exec git add . +exec git commit -m 'Add asset.txt' +exec git push + +# Checkout the forked repo and ensure asset.txt is not present +cd ../$SCRIPT_NAME-$RANDOM_STRING-fork +exec git checkout main +exec ls +! stdout asset.txt + +# Sync the forked repo with the original repo +exec gh repo sync + +# Check that asset.txt now exists in the fork +exec ls +stdout asset.txt + +-- asset.txt -- +Hello, world! \ No newline at end of file From 95ed11d9babcd3dfa41d4e1d345ef343888078d7 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 11:55:32 -0700 Subject: [PATCH 43/53] Add acceptance tests for repo deploy-key add/list/delete --- .../testdata/repos/repo-deploy-key.txtar | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 acceptance/testdata/repos/repo-deploy-key.txtar diff --git a/acceptance/testdata/repos/repo-deploy-key.txtar b/acceptance/testdata/repos/repo-deploy-key.txtar new file mode 100644 index 000000000..69c2efef8 --- /dev/null +++ b/acceptance/testdata/repos/repo-deploy-key.txtar @@ -0,0 +1,35 @@ +# Use gh as a credential helper +exec gh auth setup-git + +# Create and clone a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private --clone + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING + +# cd to the repo and list the deploy keys. There should be no keys +cd $SCRIPT_NAME-$RANDOM_STRING +exec gh repo deploy-key list --json=title +! stdout title + +# Add a deploy key +exec gh repo deploy-key add ../deployKey.pub + +# Ensure the deploy key was added +exec gh repo deploy-key list --json=title --jq='.[].title' +stdout myTitle + +# Get the deploy key id +exec gh repo deploy-key list --json=title,id --jq='.[].title="myTitle" | .[].id' +stdout2env DEPLOY_KEY_ID + +# Delete the deploy key +exec gh repo deploy-key delete $DEPLOY_KEY_ID + +# Ensure the deploy key was deleted +exec gh repo deploy-key list --json=id --jq='.[].id' +! stdout $DEPLOY_KEY_ID + +-- deployKey.pub -- +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAZmdeRNskfpvYL5YHB/YJaW8hTEXpnvPMkx5Ri+YwUr myTitle + From e7549c93f9c4069b30173320b007ca330ee9161d Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Thu, 17 Oct 2024 13:36:19 -0700 Subject: [PATCH 44/53] Cleanup some inconsistencies and improve collapse some functionality --- .../testdata/repos/repo-archive-unarchive.txtar | 2 +- acceptance/testdata/repos/repo-clone.txtar | 2 +- acceptance/testdata/repos/repo-create-view.txtar | 4 ++-- acceptance/testdata/repos/repo-delete.txtar | 2 +- acceptance/testdata/repos/repo-deploy-key.txtar | 1 - acceptance/testdata/repos/repo-edit.txtar | 4 ++-- acceptance/testdata/repos/repo-fork-sync.txtar | 2 +- acceptance/testdata/repos/repo-list-rename.txtar | 15 +++++---------- acceptance/testdata/repos/repo-set-default.txtar | 11 ++++------- 9 files changed, 17 insertions(+), 26 deletions(-) diff --git a/acceptance/testdata/repos/repo-archive-unarchive.txtar b/acceptance/testdata/repos/repo-archive-unarchive.txtar index d72b36906..de1f7df9f 100644 --- a/acceptance/testdata/repos/repo-archive-unarchive.txtar +++ b/acceptance/testdata/repos/repo-archive-unarchive.txtar @@ -23,4 +23,4 @@ exec gh repo unarchive $ORG/$SCRIPT_NAME-$RANDOM_STRING --yes # Check that the repo is unarchived exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=isArchived --jq='.isArchived' -stdout false \ No newline at end of file +stdout false diff --git a/acceptance/testdata/repos/repo-clone.txtar b/acceptance/testdata/repos/repo-clone.txtar index f0bad8e01..5afc3ab0e 100644 --- a/acceptance/testdata/repos/repo-clone.txtar +++ b/acceptance/testdata/repos/repo-clone.txtar @@ -12,4 +12,4 @@ exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING # Ensure the repo was cloned exec ls $SCRIPT_NAME-$RANDOM_STRING -stdout README.md \ No newline at end of file +stdout README.md diff --git a/acceptance/testdata/repos/repo-create-view.txtar b/acceptance/testdata/repos/repo-create-view.txtar index b5b85f593..f1a67ac73 100644 --- a/acceptance/testdata/repos/repo-create-view.txtar +++ b/acceptance/testdata/repos/repo-create-view.txtar @@ -8,5 +8,5 @@ exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING # Check that the repo exists -exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json name --jq '.name' -stdout $SCRIPT_NAME-$RANDOM_STRING \ No newline at end of file +exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=name --jq='.name' +stdout $SCRIPT_NAME-$RANDOM_STRING diff --git a/acceptance/testdata/repos/repo-delete.txtar b/acceptance/testdata/repos/repo-delete.txtar index 855473ae9..c9fd2c058 100644 --- a/acceptance/testdata/repos/repo-delete.txtar +++ b/acceptance/testdata/repos/repo-delete.txtar @@ -13,4 +13,4 @@ exec gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING # Ensure that the repo was deleted ! exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json name --jq '.name' -stderr 'Could not resolve to a Repository with the name' \ No newline at end of file +stderr 'Could not resolve to a Repository with the name' diff --git a/acceptance/testdata/repos/repo-deploy-key.txtar b/acceptance/testdata/repos/repo-deploy-key.txtar index 69c2efef8..42c5b1746 100644 --- a/acceptance/testdata/repos/repo-deploy-key.txtar +++ b/acceptance/testdata/repos/repo-deploy-key.txtar @@ -32,4 +32,3 @@ exec gh repo deploy-key list --json=id --jq='.[].id' -- deployKey.pub -- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAZmdeRNskfpvYL5YHB/YJaW8hTEXpnvPMkx5Ri+YwUr myTitle - diff --git a/acceptance/testdata/repos/repo-edit.txtar b/acceptance/testdata/repos/repo-edit.txtar index c8e293cc0..3fd5a48f6 100644 --- a/acceptance/testdata/repos/repo-edit.txtar +++ b/acceptance/testdata/repos/repo-edit.txtar @@ -9,11 +9,11 @@ defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING # Check that the repo description is empty exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json description --jq '.description' -stdout '' +! stdout '.' # Edit the repo description exec gh repo edit $ORG/$SCRIPT_NAME-$RANDOM_STRING --description 'newDescription' # Check that the repo description is updated exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json description --jq '.description' -stdout 'newDescription' \ No newline at end of file +stdout 'newDescription' diff --git a/acceptance/testdata/repos/repo-fork-sync.txtar b/acceptance/testdata/repos/repo-fork-sync.txtar index 73beb39f1..8bc437567 100644 --- a/acceptance/testdata/repos/repo-fork-sync.txtar +++ b/acceptance/testdata/repos/repo-fork-sync.txtar @@ -41,4 +41,4 @@ exec ls stdout asset.txt -- asset.txt -- -Hello, world! \ No newline at end of file +Hello, world! diff --git a/acceptance/testdata/repos/repo-list-rename.txtar b/acceptance/testdata/repos/repo-list-rename.txtar index e758ac7fd..972e5a74a 100644 --- a/acceptance/testdata/repos/repo-list-rename.txtar +++ b/acceptance/testdata/repos/repo-list-rename.txtar @@ -5,20 +5,15 @@ exec gh auth setup-git exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private # List the repos and check for the new repo -exec gh repo list $ORG --json name --jq '.[].name' +exec gh repo list $ORG --json=name --jq='.[].name' stdout $SCRIPT_NAME-$RANDOM_STRING # Rename the repo exec gh repo rename $SCRIPT_NAME-$RANDOM_STRING-renamed --repo=$ORG/$SCRIPT_NAME-$RANDOM_STRING --yes +# Defer repo deletion +defer gh repo delete $ORG/$SCRIPT_NAME-$RANDOM_STRING-renamed --yes + # List the repos and check for the renamed repo -exec gh repo list $ORG --json name --jq '.[].name' +exec gh repo list $ORG --json=name --jq='.[].name' stdout $SCRIPT_NAME-$RANDOM_STRING-renamed - -# Delete the renamed repo -exec gh repo delete $ORG/$SCRIPT_NAME-$RANDOM_STRING-renamed --yes - -# List the repos and check for the deleted repo -exec gh repo list $ORG --json name --jq '.[].name' -! stdout $SCRIPT_NAME-$RANDOM_STRING-renamed - diff --git a/acceptance/testdata/repos/repo-set-default.txtar b/acceptance/testdata/repos/repo-set-default.txtar index f8c0e68c5..c5b16b9ac 100644 --- a/acceptance/testdata/repos/repo-set-default.txtar +++ b/acceptance/testdata/repos/repo-set-default.txtar @@ -1,17 +1,14 @@ # Use gh as a credential helper exec gh auth setup-git -# Create a repository with a file so it has a default branch -exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private +# Create and clone a repository with a file so it has a default branch +exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private --clone # Defer repo cleanup defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING -# Clone the repo -exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING -cd $SCRIPT_NAME-$RANDOM_STRING - # Ensure that no default is set +cd $SCRIPT_NAME-$RANDOM_STRING exec gh repo set-default --view stderr 'no default repository has been set; use `gh repo set-default` to select one' @@ -20,4 +17,4 @@ exec gh repo set-default $ORG/$SCRIPT_NAME-$RANDOM_STRING # Check that the default is set exec gh repo set-default --view -stdout $ORG/$SCRIPT_NAME-$RANDOM_STRING \ No newline at end of file +stdout $ORG/$SCRIPT_NAME-$RANDOM_STRING From a5a77532dfd13162c89cad201eba92e0329df82e Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Fri, 18 Oct 2024 08:40:33 -0700 Subject: [PATCH 45/53] Remove unnecessary gh auth setup-git steps --- acceptance/testdata/repos/repo-archive-unarchive.txtar | 3 --- acceptance/testdata/repos/repo-clone.txtar | 3 --- acceptance/testdata/repos/repo-create-view.txtar | 3 --- acceptance/testdata/repos/repo-delete.txtar | 3 --- acceptance/testdata/repos/repo-deploy-key.txtar | 3 --- acceptance/testdata/repos/repo-edit.txtar | 3 --- acceptance/testdata/repos/repo-list-rename.txtar | 3 --- acceptance/testdata/repos/repo-set-default.txtar | 3 --- 8 files changed, 24 deletions(-) diff --git a/acceptance/testdata/repos/repo-archive-unarchive.txtar b/acceptance/testdata/repos/repo-archive-unarchive.txtar index de1f7df9f..79122a80c 100644 --- a/acceptance/testdata/repos/repo-archive-unarchive.txtar +++ b/acceptance/testdata/repos/repo-archive-unarchive.txtar @@ -1,6 +1,3 @@ -# Use gh as a credential helper -exec gh auth setup-git - # Create a repository with a file so it has a default branch exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private diff --git a/acceptance/testdata/repos/repo-clone.txtar b/acceptance/testdata/repos/repo-clone.txtar index 5afc3ab0e..f08953be1 100644 --- a/acceptance/testdata/repos/repo-clone.txtar +++ b/acceptance/testdata/repos/repo-clone.txtar @@ -1,6 +1,3 @@ -# Use gh as a credential helper -exec gh auth setup-git - # Create a repository with a file so it has a default branch exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private diff --git a/acceptance/testdata/repos/repo-create-view.txtar b/acceptance/testdata/repos/repo-create-view.txtar index f1a67ac73..9774def35 100644 --- a/acceptance/testdata/repos/repo-create-view.txtar +++ b/acceptance/testdata/repos/repo-create-view.txtar @@ -1,6 +1,3 @@ -# Use gh as a credential helper -exec gh auth setup-git - # Create a repository with a file so it has a default branch exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private diff --git a/acceptance/testdata/repos/repo-delete.txtar b/acceptance/testdata/repos/repo-delete.txtar index c9fd2c058..2e0bbc62a 100644 --- a/acceptance/testdata/repos/repo-delete.txtar +++ b/acceptance/testdata/repos/repo-delete.txtar @@ -1,6 +1,3 @@ -# Use gh as a credential helper -exec gh auth setup-git - # Create a repository with a file so it has a default branch exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private diff --git a/acceptance/testdata/repos/repo-deploy-key.txtar b/acceptance/testdata/repos/repo-deploy-key.txtar index 42c5b1746..d93d07ee5 100644 --- a/acceptance/testdata/repos/repo-deploy-key.txtar +++ b/acceptance/testdata/repos/repo-deploy-key.txtar @@ -1,6 +1,3 @@ -# Use gh as a credential helper -exec gh auth setup-git - # Create and clone a repository with a file so it has a default branch exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private --clone diff --git a/acceptance/testdata/repos/repo-edit.txtar b/acceptance/testdata/repos/repo-edit.txtar index 3fd5a48f6..00d3cdd2c 100644 --- a/acceptance/testdata/repos/repo-edit.txtar +++ b/acceptance/testdata/repos/repo-edit.txtar @@ -1,6 +1,3 @@ -# Use gh as a credential helper -exec gh auth setup-git - # Create a repository with a file so it has a default branch exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private diff --git a/acceptance/testdata/repos/repo-list-rename.txtar b/acceptance/testdata/repos/repo-list-rename.txtar index 972e5a74a..7f3ff1281 100644 --- a/acceptance/testdata/repos/repo-list-rename.txtar +++ b/acceptance/testdata/repos/repo-list-rename.txtar @@ -1,6 +1,3 @@ -# Use gh as a credential helper -exec gh auth setup-git - # Create a repository with a file so it has a default branch exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private diff --git a/acceptance/testdata/repos/repo-set-default.txtar b/acceptance/testdata/repos/repo-set-default.txtar index c5b16b9ac..4f7fa3273 100644 --- a/acceptance/testdata/repos/repo-set-default.txtar +++ b/acceptance/testdata/repos/repo-set-default.txtar @@ -1,6 +1,3 @@ -# Use gh as a credential helper -exec gh auth setup-git - # Create and clone a repository with a file so it has a default branch exec gh repo create $ORG/$SCRIPT_NAME-$RANDOM_STRING --add-readme --private --clone From ee0d9ab901843a9bd106395928a627b77af63731 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Fri, 18 Oct 2024 08:44:36 -0700 Subject: [PATCH 46/53] Wrap boolean strings in '' so it is clear they are strings --- acceptance/testdata/repos/repo-archive-unarchive.txtar | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/acceptance/testdata/repos/repo-archive-unarchive.txtar b/acceptance/testdata/repos/repo-archive-unarchive.txtar index 79122a80c..33ff519f3 100644 --- a/acceptance/testdata/repos/repo-archive-unarchive.txtar +++ b/acceptance/testdata/repos/repo-archive-unarchive.txtar @@ -6,18 +6,18 @@ defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING # Check that the repo exists and isn't archived exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=isArchived --jq='.isArchived' -stdout false +stdout 'false' # Archive the repo exec gh repo archive $ORG/$SCRIPT_NAME-$RANDOM_STRING --yes # Check that the repo is archived exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=isArchived --jq='.isArchived' -stdout true +stdout 'true' # Unarchive the repo exec gh repo unarchive $ORG/$SCRIPT_NAME-$RANDOM_STRING --yes # Check that the repo is unarchived exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json=isArchived --jq='.isArchived' -stdout false +stdout 'false' From 25f2956e671721a153ded1822f2e11be0644b4e3 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Fri, 18 Oct 2024 08:45:02 -0700 Subject: [PATCH 47/53] Replace LICENSE Makefile README.md acceptance api bin build cmd context docs git go.mod go.sum internal pkg script share test utils commands with --- acceptance/testdata/repos/repo-clone.txtar | 3 +-- acceptance/testdata/repos/repo-fork-sync.txtar | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/acceptance/testdata/repos/repo-clone.txtar b/acceptance/testdata/repos/repo-clone.txtar index f08953be1..b90a0894b 100644 --- a/acceptance/testdata/repos/repo-clone.txtar +++ b/acceptance/testdata/repos/repo-clone.txtar @@ -8,5 +8,4 @@ defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING # Ensure the repo was cloned -exec ls $SCRIPT_NAME-$RANDOM_STRING -stdout README.md +exists $SCRIPT_NAME-$RANDOM_STRING/README.md diff --git a/acceptance/testdata/repos/repo-fork-sync.txtar b/acceptance/testdata/repos/repo-fork-sync.txtar index 8bc437567..5b2362ffe 100644 --- a/acceptance/testdata/repos/repo-fork-sync.txtar +++ b/acceptance/testdata/repos/repo-fork-sync.txtar @@ -30,15 +30,13 @@ exec git push # Checkout the forked repo and ensure asset.txt is not present cd ../$SCRIPT_NAME-$RANDOM_STRING-fork exec git checkout main -exec ls -! stdout asset.txt +! exists asset.txt # Sync the forked repo with the original repo exec gh repo sync # Check that asset.txt now exists in the fork -exec ls -stdout asset.txt +exists asset.txt -- asset.txt -- Hello, world! From 6c3ad5011b7acb076a039582d52eb6f4f72b16fb Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Fri, 18 Oct 2024 08:47:15 -0700 Subject: [PATCH 48/53] Remove unnecessary flags from repo-delete testscript --- acceptance/testdata/repos/repo-delete.txtar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acceptance/testdata/repos/repo-delete.txtar b/acceptance/testdata/repos/repo-delete.txtar index 2e0bbc62a..b82388068 100644 --- a/acceptance/testdata/repos/repo-delete.txtar +++ b/acceptance/testdata/repos/repo-delete.txtar @@ -9,5 +9,5 @@ stdout $SCRIPT_NAME-$RANDOM_STRING exec gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING # Ensure that the repo was deleted -! exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING --json name --jq '.name' +! exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING stderr 'Could not resolve to a Repository with the name' From 3f4a2aea2f95d41b633ade524dc800424a884228 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Fri, 18 Oct 2024 09:22:58 -0700 Subject: [PATCH 49/53] Rename acceptance test directory from repos to repo --- acceptance/acceptance_test.go | 4 ++-- .../testdata/{repos => repo}/repo-archive-unarchive.txtar | 0 acceptance/testdata/{repos => repo}/repo-clone.txtar | 0 acceptance/testdata/{repos => repo}/repo-create-view.txtar | 0 acceptance/testdata/{repos => repo}/repo-delete.txtar | 0 acceptance/testdata/{repos => repo}/repo-deploy-key.txtar | 0 acceptance/testdata/{repos => repo}/repo-edit.txtar | 0 acceptance/testdata/{repos => repo}/repo-fork-sync.txtar | 0 acceptance/testdata/{repos => repo}/repo-list-rename.txtar | 0 acceptance/testdata/{repos => repo}/repo-set-default.txtar | 0 10 files changed, 2 insertions(+), 2 deletions(-) rename acceptance/testdata/{repos => repo}/repo-archive-unarchive.txtar (100%) rename acceptance/testdata/{repos => repo}/repo-clone.txtar (100%) rename acceptance/testdata/{repos => repo}/repo-create-view.txtar (100%) rename acceptance/testdata/{repos => repo}/repo-delete.txtar (100%) rename acceptance/testdata/{repos => repo}/repo-deploy-key.txtar (100%) rename acceptance/testdata/{repos => repo}/repo-edit.txtar (100%) rename acceptance/testdata/{repos => repo}/repo-fork-sync.txtar (100%) rename acceptance/testdata/{repos => repo}/repo-list-rename.txtar (100%) rename acceptance/testdata/{repos => repo}/repo-set-default.txtar (100%) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 366d88cf4..18757cda7 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -72,12 +72,12 @@ func TestReleases(t *testing.T) { testscript.Run(t, testScriptParamsFor(tsEnv, "release")) } -func TestRepos(t *testing.T) { +func TestRepo(t *testing.T) { var tsEnv testScriptEnv if err := tsEnv.fromEnv(); err != nil { t.Fatal(err) } - testscript.Run(t, testScriptParamsFor(tsEnv, "repos")) + testscript.Run(t, testScriptParamsFor(tsEnv, "repo")) } func testScriptParamsFor(tsEnv testScriptEnv, command string) testscript.Params { diff --git a/acceptance/testdata/repos/repo-archive-unarchive.txtar b/acceptance/testdata/repo/repo-archive-unarchive.txtar similarity index 100% rename from acceptance/testdata/repos/repo-archive-unarchive.txtar rename to acceptance/testdata/repo/repo-archive-unarchive.txtar diff --git a/acceptance/testdata/repos/repo-clone.txtar b/acceptance/testdata/repo/repo-clone.txtar similarity index 100% rename from acceptance/testdata/repos/repo-clone.txtar rename to acceptance/testdata/repo/repo-clone.txtar diff --git a/acceptance/testdata/repos/repo-create-view.txtar b/acceptance/testdata/repo/repo-create-view.txtar similarity index 100% rename from acceptance/testdata/repos/repo-create-view.txtar rename to acceptance/testdata/repo/repo-create-view.txtar diff --git a/acceptance/testdata/repos/repo-delete.txtar b/acceptance/testdata/repo/repo-delete.txtar similarity index 100% rename from acceptance/testdata/repos/repo-delete.txtar rename to acceptance/testdata/repo/repo-delete.txtar diff --git a/acceptance/testdata/repos/repo-deploy-key.txtar b/acceptance/testdata/repo/repo-deploy-key.txtar similarity index 100% rename from acceptance/testdata/repos/repo-deploy-key.txtar rename to acceptance/testdata/repo/repo-deploy-key.txtar diff --git a/acceptance/testdata/repos/repo-edit.txtar b/acceptance/testdata/repo/repo-edit.txtar similarity index 100% rename from acceptance/testdata/repos/repo-edit.txtar rename to acceptance/testdata/repo/repo-edit.txtar diff --git a/acceptance/testdata/repos/repo-fork-sync.txtar b/acceptance/testdata/repo/repo-fork-sync.txtar similarity index 100% rename from acceptance/testdata/repos/repo-fork-sync.txtar rename to acceptance/testdata/repo/repo-fork-sync.txtar diff --git a/acceptance/testdata/repos/repo-list-rename.txtar b/acceptance/testdata/repo/repo-list-rename.txtar similarity index 100% rename from acceptance/testdata/repos/repo-list-rename.txtar rename to acceptance/testdata/repo/repo-list-rename.txtar diff --git a/acceptance/testdata/repos/repo-set-default.txtar b/acceptance/testdata/repo/repo-set-default.txtar similarity index 100% rename from acceptance/testdata/repos/repo-set-default.txtar rename to acceptance/testdata/repo/repo-set-default.txtar From ba324d85ebc3c210c445b93c86daa72f1ee57191 Mon Sep 17 00:00:00 2001 From: Tyler McGoffin Date: Fri, 18 Oct 2024 09:34:13 -0700 Subject: [PATCH 50/53] Wrap true in '' in repo-fork-sync --- acceptance/testdata/repo/repo-fork-sync.txtar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acceptance/testdata/repo/repo-fork-sync.txtar b/acceptance/testdata/repo/repo-fork-sync.txtar index 5b2362ffe..6ed7b94e1 100644 --- a/acceptance/testdata/repo/repo-fork-sync.txtar +++ b/acceptance/testdata/repo/repo-fork-sync.txtar @@ -18,7 +18,7 @@ sleep 5 # Check that the repo was forked exec gh repo view $ORG/$SCRIPT_NAME-$RANDOM_STRING-fork --json='isFork' --jq='.isFork' -stdout true +stdout 'true' # Modify original repo cd $SCRIPT_NAME-$RANDOM_STRING From f4f161c09686225d2ee9981620073a13081cce67 Mon Sep 17 00:00:00 2001 From: Andy Feller Date: Fri, 18 Oct 2024 15:56:03 -0400 Subject: [PATCH 51/53] Refactor `gh secret` testscript This is a bit of a refactor based on the work done in `gh workflow` as a better approach to verify secrets created are what we expect. Changes made: 1. Removed `env2lower` as it wasn't being used in testscripts 2. Added `replace` custom command to deal with testing organization workflow secrets 3. Refactored secret testscripts to create and run workflow that tests the value of the secret provided 4. Minor reordering of test `acceptance` test functions as appending to the end is confusing and adds conflicts 5. Removed stdout TTY assertions --- acceptance/README.md | 23 +++-- acceptance/acceptance_test.go | 93 +++++++++++-------- acceptance/testdata/secret/secret-org.txtar | 85 +++++++++++++++-- .../testdata/secret/secret-repo-env.txtar | 75 ++++++++++++--- acceptance/testdata/secret/secret-repo.txtar | 71 ++++++++++++-- 5 files changed, 272 insertions(+), 75 deletions(-) diff --git a/acceptance/README.md b/acceptance/README.md index 732369bc0..82d7e1ab6 100644 --- a/acceptance/README.md +++ b/acceptance/README.md @@ -72,13 +72,6 @@ The following custom commands are defined within [`acceptance_test.go`](./accept defer gh repo delete --yes $ORG/$SCRIPT_NAME-$RANDOM_STRING ``` -- `env2lower`: set environment variable to the lowercase version of another environment variable - - ```txtar - # Prepare repository name, which is only lowercase - env2lower REPO_NAME=$RANDOM_STRING - ``` - - `env2upper`: set environment variable to the uppercase version of another environment variable ```txtar @@ -86,6 +79,22 @@ The following custom commands are defined within [`acceptance_test.go`](./accept env2upper ORG_SECRET_NAME=$RANDOM_STRING ``` +- `replace`: replace placeholders in file with interpolated content provided + + ```txtar + env2upper SECRET_NAME=$SCRIPT_NAME_$RANDOM_STRING + + # Modify workflow file to use generated organization secret name + mv ../workflow.yml .github/workflows/workflow.yml + replace .github/workflows/workflow.yml SECRET_NAME=$SECRET_NAME + + -- workflow.yml -- + on: + workflow_dispatch: + env: + ORG_SECRET: ${{ secrets.$SECRET_NAME }} + ``` + - `stdout2env`: set environment variable containing standard output from previous command ```txtar diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index e3f439d36..58e27f506 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -27,13 +27,13 @@ func TestMain(m *testing.M) { })) } -func TestPullRequests(t *testing.T) { +func TestAPI(t *testing.T) { var tsEnv testScriptEnv if err := tsEnv.fromEnv(); err != nil { t.Fatal(err) } - testscript.Run(t, testScriptParamsFor(tsEnv, "pr")) + testscript.Run(t, testScriptParamsFor(tsEnv, "api")) } func TestIssues(t *testing.T) { @@ -45,6 +45,24 @@ func TestIssues(t *testing.T) { testscript.Run(t, testScriptParamsFor(tsEnv, "pr")) } +func TestPullRequests(t *testing.T) { + var tsEnv testScriptEnv + if err := tsEnv.fromEnv(); err != nil { + t.Fatal(err) + } + + testscript.Run(t, testScriptParamsFor(tsEnv, "pr")) +} + +func TestReleases(t *testing.T) { + var tsEnv testScriptEnv + if err := tsEnv.fromEnv(); err != nil { + t.Fatal(err) + } + + testscript.Run(t, testScriptParamsFor(tsEnv, "release")) +} + func TestSecrets(t *testing.T) { var tsEnv testScriptEnv if err := tsEnv.fromEnv(); err != nil { @@ -63,25 +81,6 @@ func TestWorkflows(t *testing.T) { testscript.Run(t, testScriptParamsFor(tsEnv, "workflow")) } -func TestAPI(t *testing.T) { - var tsEnv testScriptEnv - if err := tsEnv.fromEnv(); err != nil { - t.Fatal(err) - } - - testscript.Run(t, testScriptParamsFor(tsEnv, "api")) -} - -func TestReleases(t *testing.T) { - var tsEnv testScriptEnv - if err := tsEnv.fromEnv(); err != nil { - t.Fatal(err) - } - - testscript.Run(t, testScriptParamsFor(tsEnv, "release")) ->>>>>>> trunk -} - func testScriptParamsFor(tsEnv testScriptEnv, command string) testscript.Params { var files []string if tsEnv.script != "" { @@ -156,23 +155,6 @@ func sharedCmds(tsEnv testScriptEnv) map[string]func(ts *testscript.TestScript, } }) }, - "env2lower": func(ts *testscript.TestScript, neg bool, args []string) { - if neg { - ts.Fatalf("unsupported: ! env2lower") - } - if len(args) == 0 { - ts.Fatalf("usage: env2lower name=value ...") - } - for _, env := range args { - i := strings.Index(env, "=") - - if i < 0 { - ts.Fatalf("env2lower: argument does not match name=value") - } - - ts.Setenv(env[:i], strings.ToLower(env[i+1:])) - } - }, "env2upper": func(ts *testscript.TestScript, neg bool, args []string) { if neg { ts.Fatalf("unsupported: ! env2upper") @@ -190,6 +172,41 @@ func sharedCmds(tsEnv testScriptEnv) map[string]func(ts *testscript.TestScript, ts.Setenv(env[:i], strings.ToUpper(env[i+1:])) } }, + "replace": func(ts *testscript.TestScript, neg bool, args []string) { + if neg { + ts.Fatalf("unsupported: ! replace") + } + if len(args) < 2 { + ts.Fatalf("usage: replace file env...") + } + + src := ts.MkAbs(args[0]) + ts.Logf("replace src: %s", src) + info, err := os.Stat(src) + ts.Check(err) + mode := info.Mode() & 0o777 + data, err := os.ReadFile(src) + ts.Check(err) + + for _, arg := range args[1:] { + i := strings.Index(arg, "=") + if i < 0 { + ts.Fatalf("replace: %s argument does not match name=value", arg) + } + + name := fmt.Sprintf("$%s", arg[:i]) + value := arg[i+1:] + ts.Logf("replace %s: %s", name, value) + + // `replace` was originally built similar to `cmpenv`, expanding environment variables within a file. + // However files with content that looks like environments variable such as GitHub Actions workflows + // were being modified unexpectedly. Thus `replace` has been designed to using string replacement + // looking for `$KEY` specifically. + data = []byte(strings.ReplaceAll(string(data), name, value)) + } + + ts.Check(os.WriteFile(src, data, mode)) + }, "stdout2env": func(ts *testscript.TestScript, neg bool, args []string) { if neg { ts.Fatalf("unsupported: ! stdout2env") diff --git a/acceptance/testdata/secret/secret-org.txtar b/acceptance/testdata/secret/secret-org.txtar index d6d2fd213..2bc6a845b 100644 --- a/acceptance/testdata/secret/secret-org.txtar +++ b/acceptance/testdata/secret/secret-org.txtar @@ -1,16 +1,85 @@ -# Prepare organization secret, GitHub Actions uppercases secret names -env2upper ORG_SECRET_NAME=$RANDOM_STRING +# Setup environment variables used for testscript +env REPO=$SCRIPT_NAME-$RANDOM_STRING +env2upper SECRET_NAME=$SCRIPT_NAME_$RANDOM_STRING + +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch +exec gh repo create $ORG/$REPO --add-readme --private + +# Defer repo cleanup +defer gh repo delete --yes $ORG/$REPO + +# Clone the repo +exec gh repo clone $ORG/$REPO +cd $REPO # Confirm organization secret does not exist, will fail admin:org scope missing -! exec gh api /orgs/$ORG/actions/secrets/$ORG_SECRET_NAME -stdout '"status":"404"' +exec gh secret list --org $ORG +! stdout $SECRET_NAME # Create an organization secret -exec gh secret set $ORG_SECRET_NAME --org $ORG --body 'does not matter as cannot read it once set' +exec gh secret set $SECRET_NAME --org $ORG --body 'just an organization secret' --repos $REPO # Defer organization secret cleanup -defer gh secret delete $ORG_SECRET_NAME --org $ORG +defer gh secret delete $SECRET_NAME --org $ORG -# Confirm organization secret exists +# Verify new organization secret exists exec gh secret list --org $ORG -stdout $ORG_SECRET_NAME +stdout $SECRET_NAME + +# Commit workflow file creating dispatchable workflow able to verify secret matches +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +replace .github/workflows/workflow.yml SECRET_NAME=$SECRET_NAME +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 10 + +# Get the run ID we want to watch & delete +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# Wait for workflow to complete +exec gh run watch $RUN_ID --exit-status + +# Verify secret matched what was set earlier +exec gh run view $RUN_ID --log +stdout 'GitHub Actions secret value matches$' + +-- workflow.yml -- +# This workflow is intended to assert the value of the GitHub Actions secret was set appropriately +name: Test Workflow Name +on: + # Allow workflow to be dispatched by gh workflow run + workflow_dispatch: + +jobs: + # This workflow contains a single job called "assert" that should only pass if the GitHub Actions secret value matches + assert: + runs-on: ubuntu-latest + steps: + - name: Assert secret value matches + env: + ORG_SECRET: ${{ secrets.$SECRET_NAME }} + run: | + if [[ "$ORG_SECRET" == "just an organization secret" ]]; then + echo "GitHub Actions secret value matches" + else + echo "GitHub Actions secret value does not match" + exit 1 + fi diff --git a/acceptance/testdata/secret/secret-repo-env.txtar b/acceptance/testdata/secret/secret-repo-env.txtar index b5236ea92..a9a2c7353 100644 --- a/acceptance/testdata/secret/secret-repo-env.txtar +++ b/acceptance/testdata/secret/secret-repo-env.txtar @@ -1,8 +1,10 @@ -# Force GitHub CLI to treat testscript as TTY -env GH_FORCE_TTY=80 +# Setup environment variables used for testscript env REPO=$SCRIPT_NAME-$RANDOM_STRING -# Create a repository where the secret will be registered +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch exec gh repo create $ORG/$REPO --add-readme --private # Defer repo cleanup @@ -13,17 +15,66 @@ exec gh repo clone $ORG/$REPO cd $REPO # Create a repository environment, will fail if organization does not have environment support -exec gh api /repos/$ORG/$REPO/environments/testscripts -X PUT --jq '.name' -stdout 'testscripts' - -# Verify no repository environment secrets exist -exec gh secret list --env testscripts -stderr 'no secrets found' +exec gh api /repos/$ORG/$REPO/environments/testscripts -X PUT # Create a repository environment secret -exec gh secret set TESTSCRIPTS_ENV --env testscripts --body 'does not matter as cannot read it once set' -stdout 'Set Actions secret TESTSCRIPTS_ENV for' +exec gh secret set TESTSCRIPTS_ENV --env testscripts --body 'just a repository environment secret' # Verify new repository secret exists exec gh secret list --env testscripts -stdout 'TESTSCRIPTS_ENV\s+less than a minute ago' +stdout 'TESTSCRIPTS_ENV' + +# Commit workflow file creating dispatchable workflow able to verify secret matches +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 10 + +# Get the run ID we want to watch & delete +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# Wait for workflow to complete +exec gh run watch $RUN_ID --exit-status + +# Verify secret matched what was set earlier +exec gh run view $RUN_ID --log +stdout 'GitHub Actions secret value matches$' + +-- workflow.yml -- +# This workflow is intended to assert the value of the GitHub Actions secret was set appropriately +name: Test Workflow Name +on: + # Allow workflow to be dispatched by gh workflow run + workflow_dispatch: + +jobs: + # This workflow contains a single job called "assert" that should only pass if the GitHub Actions secret value matches + assert: + runs-on: ubuntu-latest + environment: testscripts + steps: + - name: Assert secret value matches + env: + TESTSCRIPTS_ENV: ${{ secrets.TESTSCRIPTS_ENV }} + run: | + if [[ "$TESTSCRIPTS_ENV" == "just a repository environment secret" ]]; then + echo "GitHub Actions secret value matches" + else + echo "GitHub Actions secret value does not match" + exit 1 + fi diff --git a/acceptance/testdata/secret/secret-repo.txtar b/acceptance/testdata/secret/secret-repo.txtar index f69a06e57..ed336626f 100644 --- a/acceptance/testdata/secret/secret-repo.txtar +++ b/acceptance/testdata/secret/secret-repo.txtar @@ -1,8 +1,10 @@ -# Force GitHub CLI to treat testscript as TTY -env GH_FORCE_TTY=80 +# Setup environment variables used for testscript env REPO=$SCRIPT_NAME-$RANDOM_STRING -# Create a repository where the secret will be registered +# Use gh as a credential helper +exec gh auth setup-git + +# Create a repository with a file so it has a default branch exec gh repo create $ORG/$REPO --add-readme --private # Defer repo cleanup @@ -12,14 +14,63 @@ defer gh repo delete --yes $ORG/$REPO exec gh repo clone $ORG/$REPO cd $REPO -# Verify no repository secrets exist -exec gh secret list -stderr 'no secrets found' - # Create a repository secret -exec gh secret set TESTSCRIPTS --body 'does not matter as cannot read it once set' -stdout 'Set Actions secret TESTSCRIPTS for' +exec gh secret set TESTSCRIPTS --body 'just a repository secret' # Verify new repository secret exists exec gh secret list -stdout 'TESTSCRIPTS\s+less than a minute ago' +stdout 'TESTSCRIPTS' + +# Commit workflow file creating dispatchable workflow able to verify secret matches +mkdir .github/workflows +mv ../workflow.yml .github/workflows/workflow.yml +exec git add .github/workflows/workflow.yml +exec git commit -m 'Create workflow file' +exec git push -u origin main + +# Sleep because it takes a second for the workflow to register +sleep 1 + +# Check the workflow is indeed created +exec gh workflow list +stdout 'Test Workflow Name' + +# Run the workflow +exec gh workflow run 'Test Workflow Name' + +# It takes some time for a workflow run to register +sleep 10 + +# Get the run ID we want to watch & delete +exec gh run list --json databaseId --jq '.[0].databaseId' +stdout2env RUN_ID + +# Wait for workflow to complete +exec gh run watch $RUN_ID --exit-status + +# Verify secret matched what was set earlier +exec gh run view $RUN_ID --log +stdout 'GitHub Actions secret value matches$' + +-- workflow.yml -- +# This workflow is intended to assert the value of the GitHub Actions secret was set appropriately +name: Test Workflow Name +on: + # Allow workflow to be dispatched by gh workflow run + workflow_dispatch: + +jobs: + # This workflow contains a single job called "assert" that should only pass if the GitHub Actions secret value matches + assert: + runs-on: ubuntu-latest + steps: + - name: Assert secret value matches + env: + TESTSCRIPTS: ${{ secrets.TESTSCRIPTS }} + run: | + if [[ "$TESTSCRIPTS" == "just a repository secret" ]]; then + echo "GitHub Actions secret value matches" + else + echo "GitHub Actions secret value does not match" + exit 1 + fi From acf62dacf2a42ad094ff19e0442f87e3da19e528 Mon Sep 17 00:00:00 2001 From: Andy Feller Date: Mon, 21 Oct 2024 11:53:05 -0400 Subject: [PATCH 52/53] Address @williammartin PR feedback --- acceptance/README.md | 2 +- acceptance/acceptance_test.go | 10 ++++++++-- acceptance/testdata/secret/secret-org.txtar | 4 ++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/acceptance/README.md b/acceptance/README.md index 82d7e1ab6..750cb75d1 100644 --- a/acceptance/README.md +++ b/acceptance/README.md @@ -57,7 +57,7 @@ The following custom environment variables are made available to the scripts: * `ORG`: Set to the value of the `GH_ACCEPTANCE_ORG` env var provided to `go test` * `GH_TOKEN`: Set to the value of the `GH_ACCEPTANCE_TOKEN` env var provided to `go test` * `RANDOM_STRING`: Set to a length 10 random string of letters to help isolate globally visible resources - * `SCRIPT_NAME`: Set to the name of the `testscript` currently running, without extension e.g. `pr-view` + * `SCRIPT_NAME`: Set to the name of the `testscript` currently running, without extension and replacing hyphens with underscores e.g. `pr_view` * `HOME`: Set to the initial working directory. Required for `git` operations * `GH_CONFIG_DIR`: Set to the initial working directory. Required for `gh` operations diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 58e27f506..de708e38c 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -111,7 +111,11 @@ func sharedSetup(tsEnv testScriptEnv) func(ts *testscript.Env) error { if !ok { ts.T().Fatal("script name not found") } - ts.Setenv("SCRIPT_NAME", scriptName) + + // When using script name to uniquely identify where test data comes from, + // some places like GitHub Actions secret names don't accept hyphens. + // Replace them with underscores until such a time this becomes a problem. + ts.Setenv("SCRIPT_NAME", strings.ReplaceAll(scriptName, "-", "_")) ts.Setenv("HOME", ts.Cd) ts.Setenv("GH_CONFIG_DIR", ts.Cd) @@ -182,6 +186,8 @@ func sharedCmds(tsEnv testScriptEnv) map[string]func(ts *testscript.TestScript, src := ts.MkAbs(args[0]) ts.Logf("replace src: %s", src) + + // Preserve the existing file mode while replacing the contents similar to native cp behavior info, err := os.Stat(src) ts.Check(err) mode := info.Mode() & 0o777 @@ -198,7 +204,7 @@ func sharedCmds(tsEnv testScriptEnv) map[string]func(ts *testscript.TestScript, value := arg[i+1:] ts.Logf("replace %s: %s", name, value) - // `replace` was originally built similar to `cmpenv`, expanding environment variables within a file. + // `replace` was originally built similar to `cp` and `cmpenv`, expanding environment variables within a file. // However files with content that looks like environments variable such as GitHub Actions workflows // were being modified unexpectedly. Thus `replace` has been designed to using string replacement // looking for `$KEY` specifically. diff --git a/acceptance/testdata/secret/secret-org.txtar b/acceptance/testdata/secret/secret-org.txtar index 2bc6a845b..7d383009c 100644 --- a/acceptance/testdata/secret/secret-org.txtar +++ b/acceptance/testdata/secret/secret-org.txtar @@ -1,6 +1,6 @@ # Setup environment variables used for testscript -env REPO=$SCRIPT_NAME-$RANDOM_STRING -env2upper SECRET_NAME=$SCRIPT_NAME_$RANDOM_STRING +env REPO=${SCRIPT_NAME}-${RANDOM_STRING} +env2upper SECRET_NAME=${SCRIPT_NAME}_${RANDOM_STRING} # Use gh as a credential helper exec gh auth setup-git From 1736de2cd10f5c3da582edc789cbbcd213cb989b Mon Sep 17 00:00:00 2001 From: bagtoad <47394200+BagToad@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:20:37 -0600 Subject: [PATCH 53/53] Fix single quote not expanding vars --- acceptance/testdata/search/search-issues.txtar | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/acceptance/testdata/search/search-issues.txtar b/acceptance/testdata/search/search-issues.txtar index e41bc1eb6..82184f3f1 100644 --- a/acceptance/testdata/search/search-issues.txtar +++ b/acceptance/testdata/search/search-issues.txtar @@ -9,11 +9,12 @@ exec gh repo clone $ORG/$SCRIPT_NAME-$RANDOM_STRING # Create an issue in the repo cd $SCRIPT_NAME-$RANDOM_STRING -exec gh issue create --title 'Feature Request' --body 'Feature Body $RANDOM_STRING' + +exec gh issue create --title 'Feature Request' --body $RANDOM_STRING # It takes some time for the issue to be created and indexed sleep 5 # Search for the issue -exec gh search issues 'Feature Body $RANDOM_STRING' -R $ORG/$SCRIPT_NAME-$RANDOM_STRING -stdout 'Feature Request' \ No newline at end of file +exec gh search issues $RANDOM_STRING -R $ORG/$SCRIPT_NAME-$RANDOM_STRING +stdout $RANDOM_STRING \ No newline at end of file