Repository: mmcloughlin/avo
Pull request #228 (2021-11-11 01:11:50)

tests/thirdparty: add skip option

codecov-commenter: # [Codecov](https://codecov.io/gh/mmcloughlin/avo/pull/228?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin) Report
> Merging [#228](https://codecov.io/gh/mmcloughlin/avo/pull/228?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin) (20d44f1) into [master](https://codecov.io/gh/mmcloughlin/avo/commit/6c0ed1c4e8934add6379ad5ba32bf0e4e9c5bca7?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin) (6c0ed1c) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/mmcloughlin/avo/pull/228/graphs/tree.svg?width=650&height=150&src=pr&token=DaOLKxzdQS&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin)](https://codecov.io/gh/mmcloughlin/avo/pull/228?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin)

```diff
@@           Coverage Diff           @@
##           master     #228   +/-   ##
=======================================
  Coverage   75.52%   75.52%           
=======================================
  Files          58       58           
  Lines       35212    35212           
=======================================
  Hits        26595    26595           
  Misses       8464     8464           
  Partials      153      153           
```

| Flag | Coverage Δ | |
|---|---|---|
| integration | `8.81% <ø> (ø)` | |
| unittests | `73.18% <ø> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/mmcloughlin/avo/pull/228?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin) | Coverage Δ | |
|---|---|---|
| [tests/thirdparty/config.go](https://codecov.io/gh/mmcloughlin/avo/pull/228/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin#diff-dGVzdHMvdGhpcmRwYXJ0eS9jb25maWcuZ28=) | `91.66% <ø> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/mmcloughlin/avo/pull/228?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/mmcloughlin/avo/pull/228?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin). Last update [6c0ed1c...20d44f1](https://codecov.io/gh/mmcloughlin/avo/pull/228?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+McLoughlin).


Patch:
diff --git a/internal/github/client.go b/internal/github/client.go
index 84fb2fa..c7adc89 100644
--- a/internal/github/client.go
+++ b/internal/github/client.go
@@ -68,6 +68,24 @@ func (c *Client) Repository(ctx context.Context, owner, name string) (*Repositor
 	return repo, nil
 }
 
+// Issue gets information about the given Github issue.
+func (c *Client) Issue(ctx context.Context, owner, name string, number int) (*Issue, error) {
+	// Build request.
+	u := fmt.Sprintf("%s/repos/%s/%s/issues/%d", c.base, owner, name, number)
+	req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	// Execute.
+	issue := &Issue{}
+	if err := c.request(req, issue); err != nil {
+		return nil, err
+	}
+
+	return issue, nil
+}
+
 func (c *Client) request(req *http.Request, payload interface{}) (err error) {
 	// Add common headers.
 	if c.token != "" {
diff --git a/internal/github/models.go b/internal/github/models.go
index 15553c8..18a36ac 100644
--- a/internal/github/models.go
+++ b/internal/github/models.go
@@ -86,6 +86,70 @@ type Repository struct {
 	SubscribersCount int           `json:"subscribers_count"`
 }
 
+// Issue is a Github issue.
+type Issue struct {
+	URL               string            `json:"url"`
+	RepositoryURL     string            `json:"repository_url"`
+	LabelsURL         string            `json:"labels_url"`
+	CommentsURL       string            `json:"comments_url"`
+	EventsURL         string            `json:"events_url"`
+	HTMLURL           string            `json:"html_url"`
+	ID                int               `json:"id"`
+	NodeID            string            `json:"node_id"`
+	Number            int               `json:"number"`
+	Title             string            `json:"title"`
+	User              *User             `json:"user"`
+	Labels            []*Label          `json:"labels"`
+	State             string            `json:"state"`
+	Locked            bool              `json:"locked"`
+	Assignee          *User             `json:"assignee"`
+	Assignees         []*User           `json:"assignees"`
+	Comments          int               `json:"comments"`
+	CreatedAt         time.Time         `json:"created_at"`
+	UpdatedAt         time.Time         `json:"updated_at"`
+	ClosedAt          time.Time         `json:"closed_at"`
+	AuthorAssociation string            `json:"author_association"`
+	ActiveLockReason  string            `json:"active_lock_reason"`
+	PullRequestLinks  *PullRequestLinks `json:"pull_request"`
+	Body              string            `json:"body"`
+	ClosedBy          *User             `json:"closed_by"`
+	Reactions         *Reactions        `json:"reactions"`
+	TimelineURL       string            `json:"timeline_url"`
+}
+
+// Label is a Github label on an issue or PR.
+type Label struct {
+	ID          int    `json:"id"`
+	NodeID      string `json:"node_id"`
+	URL         string `json:"url"`
+	Name        string `json:"name"`
+	Color       string `json:"color"`
+	Default     bool   `json:"default"`
+	Description string `json:"description"`
+}
+
+// Reactions summarizes Github reactions.
+type Reactions struct {
+	URL        string `json:"url"`
+	TotalCount int    `json:"total_count"`
+	PlusOne    int    `json:"+1"`
+	MinusOne   int    `json:"-1"`
+	Laugh      int    `json:"laugh"`
+	Hooray     int    `json:"hooray"`
+	Confused   int    `json:"confused"`
+	Heart      int    `json:"heart"`
+	Rocket     int    `json:"rocket"`
+	Eyes       int    `json:"eyes"`
+}
+
+// PullRequestLinks are attached to an Issue object when it represents a PR.
+type PullRequestLinks struct {
+	URL      string `json:"url"`
+	HTMLURL  string `json:"html_url"`
+	DiffURL  string `json:"diff_url"`
+	PatchURL string `json:"patch_url"`
+}
+
 // User is a Github user.
 type User struct {
 	Login             string `json:"login"`


Test patch:
diff --git a/internal/github/client_test.go b/internal/github/client_test.go
index 2bb54b7..fab85e7 100644
--- a/internal/github/client_test.go
+++ b/internal/github/client_test.go
@@ -25,3 +25,20 @@ func TestClientRepository(t *testing.T) {
 	}
 	t.Logf("repository = %s", j)
 }
+
+func TestClientIssue(t *testing.T) {
+	test.RequiresNetwork(t)
+
+	ctx := context.Background()
+	g := NewClient(WithHTTPClient(http.DefaultClient), WithTokenFromEnvironment())
+	r, err := g.Issue(ctx, "octocat", "hello-world", 42)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	j, err := json.MarshalIndent(r, "", "\t")
+	if err != nil {
+		t.Fatal(err)
+	}
+	t.Logf("issue = %s", j)
+}
diff --git a/tests/thirdparty/config.go b/tests/thirdparty/config.go
index 751dc5d..afac19d 100644
--- a/tests/thirdparty/config.go
+++ b/tests/thirdparty/config.go
@@ -93,6 +93,11 @@ type Package struct {
 
 	// Test steps. If empty, defaults to "go test ./...".
 	Test []*Step `json:"test,omitempty"`
+
+	// If the package test has a known problem, record it by setting this to a
+	// non-zero avo issue number.  If set, the package will be skipped in
+	// testing.
+	KnownIssue int `json:"known_issue,omitempty"`
 }
 
 // ID returns an identifier for the package.
@@ -101,6 +106,17 @@ func (p *Package) ID() string {
 	return strings.ReplaceAll(pkgpath, "/", "-")
 }
 
+// Skip reports whether the package test should be skipped. If skipped, a known
+// issue will be set.
+func (p *Package) Skip() bool {
+	return p.KnownIssue != 0
+}
+
+// Reason returns the reason why the test is skipped.
+func (p *Package) Reason() string {
+	return fmt.Sprintf("https://github.com/mmcloughlin/avo/issues/%d", p.KnownIssue)
+}
+
 // defaults sets or removes default field values.
 func (p *Package) defaults(set bool) {
 	for _, stage := range []struct {
diff --git a/tests/thirdparty/make_workflow.go b/tests/thirdparty/make_workflow.go
index f46f019..c1be204 100644
--- a/tests/thirdparty/make_workflow.go
+++ b/tests/thirdparty/make_workflow.go
@@ -93,6 +93,9 @@ func GenerateWorkflow(pkgs thirdparty.Packages) ([]byte, error) {
 		g.Indent()
 
 		g.Linef("runs-on: ubuntu-latest")
+		if pkg.Skip() {
+			g.Linef("if: false # skip: %s", pkg.Reason())
+		}
 		g.Linef("steps:")
 		g.Indent()
 
diff --git a/tests/thirdparty/metadata_test.go b/tests/thirdparty/metadata_test.go
index 0ed31fb..aa9a626 100644
--- a/tests/thirdparty/metadata_test.go
+++ b/tests/thirdparty/metadata_test.go
@@ -54,3 +54,39 @@ func TestPackagesFileMetadata(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func TestPackagesFileKnownIssues(t *testing.T) {
+	test.RequiresNetwork(t)
+	ctx := context.Background()
+
+	pkgs, err := LoadPackagesFile("packages.json")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	g := github.NewClient(github.WithTokenFromEnvironment())
+
+	for _, pkg := range pkgs {
+		// Skipped packages must refer to an open issue.
+		if !pkg.Skip() {
+			continue
+		}
+
+		if pkg.KnownIssue == 0 {
+			t.Errorf("%s: skipped package must refer to known issue", pkg.ID())
+		}
+
+		issue, err := g.Issue(ctx, "mmcloughlin", "avo", pkg.KnownIssue)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		if issue.State != "open" {
+			t.Errorf("%s: known issue in %s state", pkg.ID(), issue.State)
+		}
+
+		if pkg.Reason() != issue.HTMLURL {
+			t.Errorf("%s: expected skip reason to be the issue url %s", pkg.ID(), issue.HTMLURL)
+		}
+	}
+}
diff --git a/tests/thirdparty/packages_test.go b/tests/thirdparty/packages_test.go
index 8e68efe..5552779 100644
--- a/tests/thirdparty/packages_test.go
+++ b/tests/thirdparty/packages_test.go
@@ -35,6 +35,9 @@ func TestPackages(t *testing.T) {
 	for _, pkg := range pkgs {
 		pkg := pkg // scopelint
 		t.Run(pkg.ID(), func(t *testing.T) {
+			if pkg.Skip() {
+				t.Skipf("skip: %s", pkg.Reason())
+			}
 			dir, clean := test.TempDir(t)
 			if !*preserve {
 				defer clean()