Skip to content

Commit

Permalink
Merge pull request #924 from 1Password/jh/application-label-comment
Browse files Browse the repository at this point in the history
Set up application labelling and commenting
  • Loading branch information
jodyheavener authored Mar 28, 2024
2 parents 1703d23 + 26f627a commit 14c4961
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 19 deletions.
20 changes: 12 additions & 8 deletions script/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,35 @@ import (
)

func errNoProjectName(sectionTitle string) error {
return fmt.Errorf("%s: is missing project name", sectionTitle)
return fmt.Errorf("**%s** is missing project name", sectionTitle)
}

func errIncomplete(sectionTitle string) error {
return fmt.Errorf("%s: was not completed for application", sectionTitle)
return fmt.Errorf("**%s** was not completed for application", sectionTitle)
}

func errEmpty(sectionTitle string) error {
return fmt.Errorf("%s: is empty", sectionTitle)
return fmt.Errorf("**%s** is empty", sectionTitle)
}

func errMustBeChecked(sectionTitle string) error {
return fmt.Errorf("%s: must be checked", sectionTitle)
return fmt.Errorf("**%s** must be checked", sectionTitle)
}

func errInvalidAccountURL(sectionTitle string) error {
return fmt.Errorf("%s: is invalid 1Password account URL", sectionTitle)
return fmt.Errorf("**%s** is invalid 1Password account URL", sectionTitle)
}

func errContainsEmoji(sectionTitle string) error {
return fmt.Errorf("%s: cannot contain emoji characters", sectionTitle)
return fmt.Errorf("**%s** cannot contain emoji characters", sectionTitle)
}

func errParsingNumber(sectionTitle string) error {
return fmt.Errorf("%s: could not be parsed into a number", sectionTitle)
return fmt.Errorf("**%s** could not be parsed into a number", sectionTitle)
}

func errInvalidURL(sectionTitle string) error {
return fmt.Errorf("%s: is an invalid URL", sectionTitle)
return fmt.Errorf("**%s** is an invalid URL", sectionTitle)
}

func TestApplication(t *testing.T) {
Expand Down Expand Up @@ -71,6 +71,10 @@ func TestApplication(t *testing.T) {
name: "event",
expectedValid: true,
},
{
name: "project-character-test",
expectedValid: true,
},
{
name: "empty-body",
expectedValid: false,
Expand Down
106 changes: 102 additions & 4 deletions script/reviewer.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
package main

import (
"fmt"
"log"
)

type Status int

const (
Approved Status = iota
Reviewing
Invalid
New
)

type Reviewer struct {
gitHub GitHub
application Application
Expand All @@ -19,11 +29,99 @@ func (r *Reviewer) Review() {

r.application.Parse(r.gitHub.Issue)

if isTestingIssue() {
if r.application.IsValid() {
debugMessage("Application has no problems")
status := r.getStatus()
isClosed := *r.gitHub.Issue.State == "closed"

r.updateLabels(status, isClosed)
r.createComment(status, isClosed)
}

func (r *Reviewer) getStatus() Status {
if r.gitHub.IssueHasLabel(LabelStatusApproved) {
return Approved
} else if r.gitHub.IssueHasLabel(LabelStatusReviewing) {
return Reviewing
} else if r.gitHub.IssueHasLabel(LabelStatusInvalid) {
return Invalid
} else {
return New
}
}

func (r *Reviewer) createComment(status Status, isClosed bool) {
title := ""
body := ""

applicationData := fmt.Sprintf("<details>\n<summary>Application data...</summary>\n\n```json\n%s\n```\n</details>", r.application.GetData())
applicationFilePath := fmt.Sprintf("https://github.com/1Password/1password-teams-open-source/blob/main/data/%s", r.application.FileName())
approvedBody := fmt.Sprintf("This application has already been approved and changes will not be reviewed. If you would like to modify the details of your application, submit a pull request against the stored [application data](%s). If you have any questions, contact us at [[email protected]](mailto:[email protected]).", applicationFilePath)
closedBody := "This application is closed and changes will not be reviewed. If you have any questions, contact us at [[email protected]](mailto:[email protected])."

// If the issue is closed, let the user know that they can't make changes.
// If the issue was closed because it got approved, let them know how they can
// modify their application details after the fact.
if isClosed {
if status == Approved {
body = approvedBody
} else {
body = closedBody
}
// This scanerio should never occur, as an approved issue should
// immediately be closed, but let's cover all bases.
} else if status == Approved {
body = approvedBody
} else if r.application.IsValid() {
if status == Reviewing {
title = "### 👍 Application still valid"
body = fmt.Sprintf("\n\n%s\n\nWe’ve run our automated pre-checks and your updated application is still valid.", applicationData)
} else {
debugMessage("Application problems:", r.application.RenderProblems())
title = "### ✅ Your application is valid"
body = fmt.Sprintf("\n\n%s\n\nThanks for applying! Our automated pre-checks have determined your application is valid. Next step: our team will review your application and may have follow-up questions. You can still make changes to your application and it’ll be re-evaluated.", applicationData)
}
} else {
title = "### ❌ Your application is invalid"
body = fmt.Sprintf("\n\n%s\n\nOur automated pre-checks have detected the following problems:\n\n%s\n\nUpdate this issue to correct these problems and we’ll automatically re-evaluate your application.", applicationData, r.application.RenderProblems())
}

r.gitHub.CreateIssueComment(fmt.Sprintf("%s%s", title, body))
}

func (r *Reviewer) updateLabels(status Status, isClosed bool) {
if status == Approved || isClosed {
return
}

if r.application.IsValid() {
if status == Invalid {
if err := r.gitHub.RemoveIssueLabel(LabelStatusInvalid); err != nil {
r.printErrorAndExit(
fmt.Errorf("could not remove issue label '%s': %s", LabelStatusInvalid, err.Error()),
)
}
}

if status != Reviewing {
if err := r.gitHub.AddIssueLabel(LabelStatusReviewing); err != nil {
r.printErrorAndExit(
fmt.Errorf("could not add issue label '%s': %s", LabelStatusReviewing, err.Error()),
)
}
}
} else {
if status != Invalid {
if err := r.gitHub.AddIssueLabel(LabelStatusInvalid); err != nil {
r.printErrorAndExit(
fmt.Errorf("could not add issue label '%s': %s", LabelStatusInvalid, err.Error()),
)
}
}

if status == Reviewing {
if err := r.gitHub.RemoveIssueLabel(LabelStatusReviewing); err != nil {
r.printErrorAndExit(
fmt.Errorf("could not remove issue label '%s': %s", LabelStatusReviewing, err.Error()),
)
}
}
}
}
Expand Down
60 changes: 60 additions & 0 deletions script/test-issues/valid-project-approved-closed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"id": 1801650328,
"number": 6,
"state": "closed",
"locked": false,
"title": "Application for TestDB",
"body": "### Account URL\n\ntestdb.1password.com\n\n### Non-commercial confirmation\n\n- [X] No, this account won't be used for commercial activity\n\n### Team application\n\n- [ ] Yes, this application is for a team\n\n### Event application\n\n- [ ] Yes, this application is for an event\n\n### Project name\n\nTestDB\n\n### Short description\n\nTestDB is a free and open source, community-based forum software project.\n\n### Number of team members/core contributors\n\n1\n\n### Homepage URL\n\nhttps://github.com/wendyappleed/test-db\n\n### Repository URL\n\nhttps://github.com/wendyappleed/test-db\n\n### License type\n\nMIT\n\n### License URL\n\nhttps://github.com/wendyappleed/test-db/blob/main/LICENSE.md\n\n### Age confirmation\n\n- [X] Yes, this project is at least 30 days old\n\n### Name\n\nWendy Appleseed\n\n### Email\n\[email protected]\n\n### Project role\n\nCore Maintainer\n\n### Profile or website\n\nhttps://github.com/wendyappleseed/\n\n### Can we contact you?\n\n- [X] Yes, you may contact me\n\n### Additional comments\n\nThank you!",
"user": {
"login": "wendyappleseed",
"id": 38230737,
"node_id": "MDQ6VXNlcjYzOTIwNDk=",
"avatar_url": "https://avatars.githubusercontent.com/u/38230737?v=4",
"html_url": "https://github.com/wendyappleseed",
"gravatar_id": "",
"type": "User",
"site_admin": false,
"url": "https://api.github.com/users/wendyappleseed",
"events_url": "https://api.github.com/users/wendyappleseed/events{/privacy}",
"following_url": "https://api.github.com/users/wendyappleseed/following{/other_user}",
"followers_url": "https://api.github.com/users/wendyappleseed/followers",
"gists_url": "https://api.github.com/users/wendyappleseed/gists{/gist_id}",
"organizations_url": "https://api.github.com/users/wendyappleseed/orgs",
"received_events_url": "https://api.github.com/users/wendyappleseed/received_events",
"repos_url": "https://api.github.com/users/wendyappleseed/repos",
"starred_url": "https://api.github.com/users/wendyappleseed/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/wendyappleseed/subscriptions"
},
"labels": [
{
"id": 5728067083,
"url": "https://api.github.com/repos/1Password/1password-teams-open-source/labels/status:%20approved",
"name": "status: approved",
"color": "0052CC",
"description": "The application has been approved",
"default": false,
"node_id": "LA_kwDOJ6JE6M8AAAABVWteCw"
}
],
"comments": 11,
"closed_at": "2023-07-13T05:03:51Z",
"created_at": "2023-07-12T19:49:35Z",
"updated_at": "2023-07-13T05:03:51Z",
"url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6",
"html_url": "https://github.com/wendyappleseed/1password-teams-open-source/issues/6",
"comments_url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/comments",
"events_url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/events",
"labels_url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/labels{/name}",
"repository_url": "https://api.github.com/repos/1Password/1password-teams-open-source",
"reactions": {
"total_count": 0,
"+1": 0,
"-1": 0,
"laugh": 0,
"confused": 0,
"heart": 0,
"hooray": 0,
"url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/reactions"
},
"node_id": "I_kwDOJ6JE6M5rYwCY"
}
49 changes: 49 additions & 0 deletions script/test-issues/valid-project-character-test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"id": 1801650328,
"number": 6,
"state": "open",
"locked": false,
"title": "Application for TestDB",
"body": "### Account URL\n\n`testdb.1password.com`\n\n### Non-commercial confirmation\n\n- [X] No, this account won't be used for commercial activity\n\n### 👨‍💻 Team application\n\n- [X] Yes, this application is for a team\n\n### Event application\n\n- [ ] Yes, this application is for an event\n\n### Project name\n\n`_TestDB_\n\n- test``\n\n### Short description\n\nTestDB is a free and open source, community-based forum software project.```\n\n## **This is a test comment** <img src=\"howdy.png\" />\n\n### Number of team members/core contributors\n\n1\n\n### Homepage URL\n\nhttps://github.com/wendyappleed/test-db\n\n### Repository URL\n\nhttps://github.com/wendyappleed/test-db\n\n### License type\n\nMIT\n\n### License URL\n\nhttps://github.com/wendyappleed/test-db/blob/main/LICENSE.md\n\n### Age confirmation\n\n- [X] Yes, this project is at least 30 days old\n\n### Name\n\nWendy Appleseed\n\n### Email\n\[email protected]\n\n### Project role\n\nCore Maintainer\n\n### Profile or website\n\nhttps://github.com/wendyappleseed/\n\n### Can we contact you?\n\n- [X] Yes, you may contact me\n\n### Additional comments\n\n Thank you!",
"user": {
"login": "wendyappleseed",
"id": 38230737,
"node_id": "MDQ6VXNlcjYzOTIwNDk=",
"avatar_url": "https://avatars.githubusercontent.com/u/38230737?v=4",
"html_url": "https://github.com/wendyappleseed",
"gravatar_id": "",
"type": "User",
"site_admin": false,
"url": "https://api.github.com/users/wendyappleseed",
"events_url": "https://api.github.com/users/wendyappleseed/events{/privacy}",
"following_url": "https://api.github.com/users/wendyappleseed/following{/other_user}",
"followers_url": "https://api.github.com/users/wendyappleseed/followers",
"gists_url": "https://api.github.com/users/wendyappleseed/gists{/gist_id}",
"organizations_url": "https://api.github.com/users/wendyappleseed/orgs",
"received_events_url": "https://api.github.com/users/wendyappleseed/received_events",
"repos_url": "https://api.github.com/users/wendyappleseed/repos",
"starred_url": "https://api.github.com/users/wendyappleseed/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/wendyappleseed/subscriptions"
},
"comments": 11,
"closed_at": "2023-07-13T05:03:51Z",
"created_at": "2023-07-12T19:49:35Z",
"updated_at": "2023-07-13T05:03:51Z",
"url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6",
"html_url": "https://github.com/wendyappleseed/1password-teams-open-source/issues/6",
"comments_url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/comments",
"events_url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/events",
"labels_url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/labels{/name}",
"repository_url": "https://api.github.com/repos/1Password/1password-teams-open-source",
"reactions": {
"total_count": 0,
"+1": 0,
"-1": 0,
"laugh": 0,
"confused": 0,
"heart": 0,
"hooray": 0,
"url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/reactions"
},
"node_id": "I_kwDOJ6JE6M5rYwCY"
}
60 changes: 60 additions & 0 deletions script/test-issues/valid-project-reviewing.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"id": 1801650328,
"number": 6,
"state": "open",
"locked": false,
"title": "Application for TestDB",
"body": "### Account URL\n\ntestdb.1password.com\n\n### Non-commercial confirmation\n\n- [X] No, this account won't be used for commercial activity\n\n### Team application\n\n- [ ] Yes, this application is for a team\n\n### Event application\n\n- [ ] Yes, this application is for an event\n\n### Project name\n\nTestDB\n\n### Short description\n\nTestDB is a free and open source, community-based forum software project.\n\n### Number of team members/core contributors\n\n1\n\n### Homepage URL\n\nhttps://github.com/wendyappleed/test-db\n\n### Repository URL\n\nhttps://github.com/wendyappleed/test-db\n\n### License type\n\nMIT\n\n### License URL\n\nhttps://github.com/wendyappleed/test-db/blob/main/LICENSE.md\n\n### Age confirmation\n\n- [X] Yes, this project is at least 30 days old\n\n### Name\n\nWendy Appleseed\n\n### Email\n\[email protected]\n\n### Project role\n\nCore Maintainer\n\n### Profile or website\n\nhttps://github.com/wendyappleseed/\n\n### Can we contact you?\n\n- [X] Yes, you may contact me\n\n### Additional comments\n\nThank you!",
"user": {
"login": "wendyappleseed",
"id": 38230737,
"node_id": "MDQ6VXNlcjYzOTIwNDk=",
"avatar_url": "https://avatars.githubusercontent.com/u/38230737?v=4",
"html_url": "https://github.com/wendyappleseed",
"gravatar_id": "",
"type": "User",
"site_admin": false,
"url": "https://api.github.com/users/wendyappleseed",
"events_url": "https://api.github.com/users/wendyappleseed/events{/privacy}",
"following_url": "https://api.github.com/users/wendyappleseed/following{/other_user}",
"followers_url": "https://api.github.com/users/wendyappleseed/followers",
"gists_url": "https://api.github.com/users/wendyappleseed/gists{/gist_id}",
"organizations_url": "https://api.github.com/users/wendyappleseed/orgs",
"received_events_url": "https://api.github.com/users/wendyappleseed/received_events",
"repos_url": "https://api.github.com/users/wendyappleseed/repos",
"starred_url": "https://api.github.com/users/wendyappleseed/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/wendyappleseed/subscriptions"
},
"labels": [
{
"id": 5728067083,
"url": "https://api.github.com/repos/1Password/1password-teams-open-source/labels/status:%20reviewing",
"name": "status: reviewing",
"color": "0052CC",
"description": "The application is being reviewed",
"default": false,
"node_id": "LA_kwDOJ6JE6M8AAAABVWteCw"
}
],
"comments": 11,
"closed_at": "2023-07-13T05:03:51Z",
"created_at": "2023-07-12T19:49:35Z",
"updated_at": "2023-07-13T05:03:51Z",
"url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6",
"html_url": "https://github.com/wendyappleseed/1password-teams-open-source/issues/6",
"comments_url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/comments",
"events_url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/events",
"labels_url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/labels{/name}",
"repository_url": "https://api.github.com/repos/1Password/1password-teams-open-source",
"reactions": {
"total_count": 0,
"+1": 0,
"-1": 0,
"laugh": 0,
"confused": 0,
"heart": 0,
"hooray": 0,
"url": "https://api.github.com/repos/1Password/1password-teams-open-source/issues/6/reactions"
},
"node_id": "I_kwDOJ6JE6M5rYwCY"
}
12 changes: 6 additions & 6 deletions script/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type ValidationError struct {
type ValidatorCallback func(string) (bool, string, string)

func (e *ValidationError) Error() string {
return fmt.Sprintf("%s: %s", e.Section, e.Message)
return fmt.Sprintf("**%s** %s", e.Section, e.Message)
}

type Validator struct {
Expand Down Expand Up @@ -69,18 +69,18 @@ func ParseInput(value string) (bool, string, string) {
return true, "", ""
}

return true, value, ""
}

func ParsePlainString(value string) (bool, string, string) {
// strip all formattig, except for newlines
// strip all formatting, except for newlines
html := blackfriday.Run([]byte(value))
doc, err := goquery.NewDocumentFromReader(bytes.NewReader(html))
if err != nil {
return false, value, err.Error()
}
value = strings.TrimSpace(doc.Text())

return true, value, ""
}

func ParsePlainString(value string) (bool, string, string) {
if urlRegex.MatchString(value) {
return false, value, "cannot contain URLs"
}
Expand Down
2 changes: 1 addition & 1 deletion script/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func TestParseInput(t *testing.T) {
{"_No response_", true, "", ""},
{"None", true, "", ""},
{"hello", true, "hello", ""},
{"Testing <b>formatting</b> and <a href=\"#\">link</a> stripping", true, "Testing formatting and link stripping", ""},
}
runValidationTests(t, testCases, ParseInput, "ParseInput")
}
Expand All @@ -39,7 +40,6 @@ func TestParsePlainString(t *testing.T) {
{"", true, "", ""},
{"Hello world", true, "Hello world", ""},
{"👋 howdy", false, "👋 howdy", "cannot contain emoji characters"},
{"Testing <b>formatting</b> and <a href=\"#\">link</a> stripping", true, "Testing formatting and link stripping", ""},
}
runValidationTests(t, testCases, ParsePlainString, "ParsePlainString")
}
Expand Down

0 comments on commit 14c4961

Please sign in to comment.