Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.

Commit

Permalink
[notifiers/github] Add display name annotation.
Browse files Browse the repository at this point in the history
Adds an optional annotation to control what the statuses display name in
GitHub. If not specified, this defaults to the Task's name.
  • Loading branch information
wlynch authored and tekton-robot committed Aug 10, 2021
1 parent 2f3076b commit 2d51e9d
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 74 deletions.
30 changes: 17 additions & 13 deletions notifiers/github-app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ integration values to post information back to GitHub.

This runs in 2 modes:

- GitHub App : Converts the TaskRun into a [CheckRun](https://docs.github.com/en/rest/guides/getting-started-with-the-checks-api) with
corresponding status and logs.
- GitHub OAuth : Converts the TaskRun into a [Status](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-status-checks).
- GitHub App : Converts the TaskRun into a
[CheckRun](https://docs.github.com/en/rest/guides/getting-started-with-the-checks-api)
with corresponding status and logs.
- GitHub OAuth : Converts the TaskRun into a
[Status](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-status-checks).

This does not do anything to grant the running TaskRun access to GitHub
credentials (e.g. for cloning the repo) -
Expand All @@ -20,23 +22,25 @@ fine-grained installation permissions).
The controller uses annotations with the prefix `github.integrations.tekton.dev`
to identify and track TaskRuns to publish.

| Annotation | Description |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Annotation | Description |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| github.integrations.tekton.dev/installation | (GitHub App only) GitHub App Installation ID. This can be found in GitHub webhook events under the [`installations.id` field](https://docs.github.com/en/enterprise-server@2.20/developers/webhooks-and-events/webhook-events-and-payloads#webhook-payload-object-common-properties). |
| github.integrations.tekton.dev/owner | GitHub org or user who owns the repo (for `github.com/tektoncd/test`, this should be `tektoncd`). |
| github.integrations.tekton.dev/repo | GitHub repo name (for `github.com/tektoncd/test`, this should be `test`). |
| github.integrations.tekton.dev/checkrun | (GitHub App / output only) GitHub CheckRun ID. If set, the controller will update this CheckRun instead of creating a new one. |
| github.integrations.tekton.dev/owner | GitHub org or user who owns the repo (for `github.com/tektoncd/test`, this should be `tektoncd`). |
| github.integrations.tekton.dev/repo | GitHub repo name (for `github.com/tektoncd/test`, this should be `test`). |
| github.integrations.tekton.dev/checkrun | (GitHub App / output only) GitHub CheckRun ID. If set, the controller will update this CheckRun instead of creating a new one. |
| github.integrations.tekton.dev/name | Display name to use for GitHub CheckRun/Status. If not specified, defaults to the Tasks name. |

For an example a full TaskRun with the initial annotations set, see
[pkg/controller/testdata/taskrun.yaml](pkg/controller/testdata/taskrun.yaml)
(these are the annotations you'll need to set for the notifier to work).

## Running the controller

| Environment Variable | Description |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| GITHUB_APP_ID | ID of your GitHub App. Can be found under https://github.com/settings/apps > Edit > General > About > App ID |
| GITHUB_APP_KEY | Path to the [private key of your GitHub App](https://docs.github.com/en/free-pro-team@latest/developers/apps/authenticating-with-github-apps#generating-a-private-key) |
| Environment Variable | Description |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| GITHUB_APP_ID | ID of your GitHub App. Can be found under https://github.com/settings/apps > Edit > General > About > App ID |
| GITHUB_APP_KEY | Path to the [private key of your GitHub App](https://docs.github.com/en/free-pro-team@latest/developers/apps/authenticating-with-github-apps#generating-a-private-key) |
| GITHUB_TOKEN | GitHub Personal Access Token (https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token). We strongly recommend **not** using your own personal GitHub Account - use a bot user instead. |

If both GitHub App and GitHub OAuth variables are provided, the controller will use GitHub App.
If both GitHub App and GitHub OAuth variables are provided, the controller will
use GitHub App.
8 changes: 6 additions & 2 deletions notifiers/github-app/pkg/controller/checkrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ func UpsertCheckRun(ctx context.Context, client *github.Client, tr *v1beta1.Task
owner := tr.Annotations[key("owner")]
repo := tr.Annotations[key("repo")]
commit := tr.Annotations[key("commit")]
name := tr.Annotations[key("name")]
if name == "" {
name = tr.GetNamespacedName().String()
}

status, conclusion := status(tr.Status)

Expand All @@ -85,7 +89,7 @@ func UpsertCheckRun(ctx context.Context, client *github.Client, tr *v1beta1.Task
}
cr, _, err := client.Checks.UpdateCheckRun(ctx, owner, repo, n, github.UpdateCheckRunOptions{
ExternalID: github.String(tr.GetSelfLink()),
Name: tr.Name,
Name: name,
Status: github.String(status),
Conclusion: github.String(conclusion),
HeadSHA: github.String(commit),
Expand All @@ -103,7 +107,7 @@ func UpsertCheckRun(ctx context.Context, client *github.Client, tr *v1beta1.Task
// There's no existing CheckRun - create.
cr, _, err := client.Checks.CreateCheckRun(ctx, tr.Annotations[key("owner")], tr.Annotations[key("repo")], github.CreateCheckRunOptions{
ExternalID: github.String(tr.GetSelfLink()),
Name: tr.GetNamespacedName().String(),
Name: name,
Status: github.String(status),
Conclusion: github.String(conclusion),
HeadSHA: tr.Annotations[key("commit")],
Expand Down
93 changes: 54 additions & 39 deletions notifiers/github-app/pkg/controller/checkrun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,50 +35,65 @@ import (
)

func TestUpsertCheckRun(t *testing.T) {
mux := http.NewServeMux()
srv := httptest.NewServer(mux)
client := github.NewClient(srv.Client())
client.BaseURL = mustParseURL(srv.URL + "/")

ctx := context.Background()
tr := taskrun("testdata/taskrun.yaml")

output := &github.CheckRunOutput{
Summary: github.String("foo"),
}

t.Run("Create", func(t *testing.T) {
mux.HandleFunc("/repos/tektoncd/test/check-runs", validateCheckRun(t, &github.CheckRun{
Name: github.String("default/echo-6b4fn-echo-xrxq4"),
HeadSHA: github.String("db165c3a71dc45d096aebd0f49f07ec565ad1e08"),
ExternalID: github.String("/apis/tekton.dev/v1beta1/namespaces/default/taskruns/echo-6b4fn-echo-xrxq4"),
DetailsURL: github.String("https://tekton.dev"),
Status: github.String("completed"),
Conclusion: github.String("success"),
StartedAt: &github.Timestamp{Time: time.Date(2020, 8, 27, 15, 21, 37, 0, time.FixedZone("Z", 0))},
CompletedAt: &github.Timestamp{Time: time.Date(2020, 8, 27, 15, 21, 46, 0, time.FixedZone("Z", 0))},
Output: output,
}))
if _, err := UpsertCheckRun(ctx, client, tr, output); err != nil {
t.Fatalf("UpsertCheckRun: %v", err)
}
})

t.Run("Update", func(t *testing.T) {
tr.Annotations[key("checkrun")] = "1234"
mux.HandleFunc("/repos/tektoncd/test/check-runs/1234", validateCheckRun(t, &github.CheckRun{
Name: github.String("echo-6b4fn-echo-xrxq4"),
HeadSHA: github.String("db165c3a71dc45d096aebd0f49f07ec565ad1e08"),
ExternalID: github.String("/apis/tekton.dev/v1beta1/namespaces/default/taskruns/echo-6b4fn-echo-xrxq4"),
DetailsURL: github.String("https://tekton.dev"),
Status: github.String("completed"),
Conclusion: github.String("success"),
CompletedAt: &github.Timestamp{Time: time.Date(2020, 8, 27, 15, 21, 46, 0, time.FixedZone("Z", 0))},
Output: output,
}))
if _, err := UpsertCheckRun(ctx, client, tr, output); err != nil {
t.Fatalf("UpsertCheckRun: %v", err)
}
})
for _, tc := range []struct {
nameAnnotation string
wantName string
}{
{
nameAnnotation: "",
wantName: "default/echo-6b4fn-echo-xrxq4",
},
{
nameAnnotation: "tacocat",
wantName: "tacocat",
},
} {
t.Run(tc.nameAnnotation, func(t *testing.T) {
mux := http.NewServeMux()
srv := httptest.NewServer(mux)
client := github.NewClient(srv.Client())
client.BaseURL = mustParseURL(srv.URL + "/")

tr := taskrun("testdata/taskrun.yaml")
tr.Annotations[key("name")] = tc.nameAnnotation

cr := &github.CheckRun{
Name: github.String(tc.wantName),
HeadSHA: github.String("db165c3a71dc45d096aebd0f49f07ec565ad1e08"),
ExternalID: github.String("/apis/tekton.dev/v1beta1/namespaces/default/taskruns/echo-6b4fn-echo-xrxq4"),
DetailsURL: github.String("https://tekton.dev"),
Status: github.String("completed"),
Conclusion: github.String("success"),
StartedAt: &github.Timestamp{Time: time.Date(2020, 8, 27, 15, 21, 37, 0, time.FixedZone("Z", 0))},
CompletedAt: &github.Timestamp{Time: time.Date(2020, 8, 27, 15, 21, 46, 0, time.FixedZone("Z", 0))},
Output: output,
}
t.Run("Create", func(t *testing.T) {
mux.HandleFunc("/repos/tektoncd/test/check-runs", validateCheckRun(t, cr))
if _, err := UpsertCheckRun(ctx, client, tr, output); err != nil {
t.Fatalf("UpsertCheckRun: %v", err)
}
})

t.Run("Update", func(t *testing.T) {
tr.Annotations[key("checkrun")] = "1234"

// StartedAt isn't set on update.
cr.StartedAt = nil

mux.HandleFunc("/repos/tektoncd/test/check-runs/1234", validateCheckRun(t, cr))
if _, err := UpsertCheckRun(ctx, client, tr, output); err != nil {
t.Fatalf("UpsertCheckRun: %v", err)
}
})
})
}
}

func mustParseURL(s string) *url.URL {
Expand Down
6 changes: 5 additions & 1 deletion notifiers/github-app/pkg/controller/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ func (r *GitHubAppReconciler) HandleStatus(ctx context.Context, tr *v1beta1.Task
owner := tr.Annotations[key("owner")]
repo := tr.Annotations[key("repo")]
commit := tr.Annotations[key("commit")]
name := tr.Annotations[key("name")]
if name == "" {
name = tr.GetNamespacedName().String()
}

status := &github.RepoStatus{
State: state(tr.Status),
Description: truncateDesc(tr.GetStatusCondition().GetCondition(apis.ConditionSucceeded).GetMessage()),
TargetURL: github.String(dashboardURL(tr)),
Context: github.String(tr.GetName()),
Context: github.String(name),
}
_, _, err = client.Repositories.CreateStatus(ctx, owner, repo, commit, status)
return err
Expand Down
56 changes: 37 additions & 19 deletions notifiers/github-app/pkg/controller/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,46 @@ import (
)

func TestHandleStatus(t *testing.T) {
mux := http.NewServeMux()
srv := httptest.NewServer(mux)
client := github.NewClient(srv.Client())
client.BaseURL = mustParseURL(srv.URL + "/")
ctx := context.Background()

r := &GitHubAppReconciler{
GitHub: NewStatic(client),
}
for _, tc := range []struct {
nameAnnotation string
wantName string
}{
{
nameAnnotation: "",
wantName: "default/echo-6b4fn-echo-xrxq4",
},
{
nameAnnotation: "tacocat",
wantName: "tacocat",
},
} {
t.Run(tc.nameAnnotation, func(t *testing.T) {
mux := http.NewServeMux()
srv := httptest.NewServer(mux)
client := github.NewClient(srv.Client())
client.BaseURL = mustParseURL(srv.URL + "/")

ctx := context.Background()
tr := taskrun("testdata/taskrun.yaml")
r := &GitHubAppReconciler{
GitHub: NewStatic(client),
}

tr := taskrun("testdata/taskrun.yaml")
tr.Annotations[key("name")] = tc.nameAnnotation

mux.HandleFunc("/repos/tektoncd/test/statuses/db165c3a71dc45d096aebd0f49f07ec565ad1e08",
validateStatus(t, &github.RepoStatus{
State: github.String(StateSuccess),
Description: github.String("All Steps have completed executing"),
TargetURL: github.String(dashboardURL(tr)),
Context: github.String("echo-6b4fn-echo-xrxq4"),
}),
)
if err := r.HandleStatus(ctx, tr); err != nil {
t.Fatalf("HandleStatus: %v", err)
mux.HandleFunc("/repos/tektoncd/test/statuses/db165c3a71dc45d096aebd0f49f07ec565ad1e08",
validateStatus(t, &github.RepoStatus{
State: github.String(StateSuccess),
Description: github.String("All Steps have completed executing"),
TargetURL: github.String(dashboardURL(tr)),
Context: github.String(tc.wantName),
}),
)
if err := r.HandleStatus(ctx, tr); err != nil {
t.Fatalf("HandleStatus: %v", err)
}
})
}
}

Expand Down

0 comments on commit 2d51e9d

Please sign in to comment.