diff --git a/Dockerfile b/Dockerfile index 877be33a..53721ef1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,9 +2,9 @@ ARG base_image=alpine ARG builder_image=golang FROM ${builder_image} as builder -ADD . /go/src/github.com/aoldershaw/github-pr-resource WORKDIR /go/src/github.com/aoldershaw/github-pr-resource RUN curl -sL https://taskfile.dev/install.sh | sh +ADD . /go/src/github.com/aoldershaw/github-pr-resource RUN ./bin/task build FROM ${base_image} as resource @@ -12,11 +12,10 @@ FROM ${base_image} as resource RUN apk add --update --no-cache \ git \ git-lfs \ - openssh + openssh \ + git-crypt COPY scripts/askpass.sh /usr/local/bin/askpass.sh -ADD scripts/install_git_crypt.sh install_git_crypt.sh -RUN ./install_git_crypt.sh && rm ./install_git_crypt.sh COPY --from=builder /go/src/github.com/aoldershaw/github-pr-resource/build /opt/resource diff --git a/README.md b/README.md index 1adba3d3..d9ee026d 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ for a single PR. | `v4_endpoint` | No | `https://api.github.com/graphql` | Endpoint to use for the V4 Github API (Graphql). | | `paths` | No | `["terraform/*/*.tf"]` | Only produce new versions for commits that include changes to files that match one or more glob patterns or prefixes. Note: this differs from `source.paths` when listing PRs in that it applies on a commit-by-commit basis, whereas the former applies for the full PR. | | `ignore_paths` | No | `[".ci/"]` | Inverse of the above. Pattern syntax is documented in [filepath.Match](https://golang.org/pkg/path/filepath/#Match), or a path prefix can be specified (e.g. `.ci/` will match everything in the `.ci` directory). | +| `labels` | No | `["bug", "enhancement"]` | The labels on the PR. The pipeline will only trigger on pull requests having at least one of the specified labels. | | `disable_ci_skip` | No | `true` | Disable ability to skip builds with `[ci skip]` and `[skip ci]` in the commit message. | | `git_crypt_key` | No | `AEdJVENSWVBUS0VZAAAAA...` | Base64 encoded git-crypt key. Setting this will unlock / decrypt the repository with git-crypt. To get the key simply execute `git-crypt export-key -- - | base64` in an encrypted repository. | | `disable_git_lfs` | No | `true` | Disable Git LFS, skipping an attempt to convert pointers of files tracked into their corresponding objects when checked out into a working copy. | diff --git a/cmd/check/main.go b/cmd/check/main.go index d0319190..31f485e6 100644 --- a/cmd/check/main.go +++ b/cmd/check/main.go @@ -79,12 +79,18 @@ func checkPR(stdin []byte) { log.Fatalf("failed to create temp dir: %v", err) } + // github client for checking labels + github, err := resource.NewGithubClient(request.Source.CommonConfig, request.Source.GithubConfig) + if err != nil { + log.Fatalf("failed to create github manager: %v", err) + } + // We never need git-lfs when we check for new commits, so always disable it. git, err := resource.NewGitClient(request.Source.CommonConfig, true, repoDir, os.Stderr) if err != nil { log.Fatalf("failed to create git manager: %v", err) } - response, err := pr.Check(request, git) + response, err := pr.Check(request, git, github) if err != nil { log.Fatalf("check failed: %v", err) } diff --git a/github.go b/github.go index 5dfe2f1d..a0efb170 100644 --- a/github.go +++ b/github.go @@ -204,6 +204,13 @@ func (m *GithubClient) GetPullRequest(prNumber int, commitRef string) (*PullRequ } } } `graphql:"commits(last:$commitsLast)"` + Labels struct { + Edges []struct { + Node struct { + LabelObject + } + } + } `graphql:"labels(first:$labelsFirst)"` } `graphql:"pullRequest(number:$prNumber)"` } `graphql:"repository(owner:$repositoryOwner,name:$repositoryName)"` } @@ -213,6 +220,7 @@ func (m *GithubClient) GetPullRequest(prNumber int, commitRef string) (*PullRequ "repositoryName": githubv4.String(m.Repository), "prNumber": githubv4.Int(prNumber), "commitsLast": githubv4.Int(100), + "labelsFirst": githubv4.Int(100), } // TODO: Pagination - in case someone pushes > 100 commits before the build has time to start :p @@ -220,12 +228,17 @@ func (m *GithubClient) GetPullRequest(prNumber int, commitRef string) (*PullRequ return nil, err } + labels := make([]LabelObject, len(query.Repository.PullRequest.Labels.Edges)) + for _, l := range query.Repository.PullRequest.Labels.Edges { + labels = append(labels, l.Node.LabelObject) + } for _, c := range query.Repository.PullRequest.Commits.Edges { if c.Node.Commit.OID == commitRef { // Return as soon as we find the correct ref. return &PullRequest{ PullRequestObject: query.Repository.PullRequest.PullRequestObject, Tip: c.Node.Commit, + Labels: labels, }, nil } } diff --git a/pr/check.go b/pr/check.go index 4533170b..e54d958e 100644 --- a/pr/check.go +++ b/pr/check.go @@ -1,10 +1,13 @@ package pr import ( + "fmt" + resource "github.com/aoldershaw/github-pr-resource" ) -func Check(request CheckRequest, git resource.Git) (CheckResponse, error) { +func Check(request CheckRequest, git resource.Git, manager resource.Github) (CheckResponse, error) { + // First check commits if err := git.Init(nil); err != nil { return CheckResponse{}, err } @@ -28,6 +31,27 @@ func Check(request CheckRequest, git resource.Git) (CheckResponse, error) { response[i] = Version{Ref: commit} } + if len(commits) != 0 && len(request.Source.Labels) != 0 { + // Filter by PR labels + pull, err := manager.GetPullRequest(request.Source.Number, commits[0]) + if err != nil { + return nil, fmt.Errorf("failed to get pull request: %s", err) + } + labelFound := false + LabelLoop: + for _, wantedLabel := range request.Source.Labels { + for _, targetLabel := range pull.Labels { + if targetLabel.Name == wantedLabel { + labelFound = true + break LabelLoop + } + } + } + if !labelFound { + return make(CheckResponse, 0), nil + } + } + return response, nil } diff --git a/pr/models.go b/pr/models.go index 8332c3e8..4e136ea9 100644 --- a/pr/models.go +++ b/pr/models.go @@ -16,6 +16,7 @@ type Source struct { Paths []string `json:"paths"` IgnorePaths []string `json:"ignore_paths"` DisableCISkip bool `json:"disable_ci_skip"` + Labels []string `json:"labels"` } // Validate the source configuration. diff --git a/scripts/install_git_crypt.sh b/scripts/install_git_crypt.sh deleted file mode 100755 index c56eafc4..00000000 --- a/scripts/install_git_crypt.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -set -eu - -_main() { - apk --update add --virtual=.build-deps curl make g++ openssl-dev - apk add --no-cache libgcc libstdc++ openssl - local tmpdir - tmpdir="$(mktemp -d git_crypt_install.XXXXXX)" - - cd "$tmpdir" - curl -Lo git-crypt-0.6.0.tar.gz https://www.agwa.name/projects/git-crypt/downloads/git-crypt-0.6.0.tar.gz - tar -zxf git-crypt-0.6.0.tar.gz - cd git-crypt-0.6.0 - make - make install - cd .. - rm -rf "$tmpdir" - - apk del .build-deps - rm -rf /var/cache/apk/* -} - -_main "$@"