Skip to content

Commit

Permalink
Set up logic to approve and add the data from an application to the r…
Browse files Browse the repository at this point in the history
…epository
  • Loading branch information
jodyheavener committed Mar 26, 2024
1 parent cb2c5d3 commit c3d9a0c
Show file tree
Hide file tree
Showing 5 changed files with 274 additions and 11 deletions.
69 changes: 59 additions & 10 deletions script/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"encoding/json"
"fmt"
"log"
"regexp"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -40,13 +42,14 @@ type Application struct {
sections map[string]string `json:"-"`
Problems []error `json:"-"`

Account string `json:"account"`
Project Project `json:"project"`
Applicant Applicant `json:"applicant"`
CanContact bool `json:"can_contact"`
ApproverId int `json:"approver_id,omitempty"`
IssueNumber int `json:"issue_number"`
CreatedAt time.Time `json:"created_at"`
Account string `json:"account"`
Project Project `json:"project"`
Applicant Applicant `json:"applicant"`
CanContact bool `json:"can_contact"`
ApproverId int `json:"approver_id,omitempty"`
ApproverUsername string `json:"-"`
IssueNumber int `json:"issue_number"`
CreatedAt time.Time `json:"created_at"`
}

func (a *Application) Parse(issue *github.Issue) {
Expand Down Expand Up @@ -97,7 +100,7 @@ func (a *Application) Parse(issue *github.Issue) {
a.CanContact = a.boolSection("Can we contact you?", false, ParseCheckbox)

if isTestingIssue() {
debugMessage("Application data:", a.GetData())
debugMessage("Application data:", string(a.GetData()))
}

for _, err := range a.validator.Errors {
Expand All @@ -119,13 +122,59 @@ func (a *Application) RenderProblems() string {
return strings.Join(problemStrings, "\n")
}

func (a *Application) GetData() string {
func (a *Application) GetData() []byte {
data, err := json.MarshalIndent(a, "", "\t")
if err != nil {
log.Fatalf("Could not marshal Application data: %s", err.Error())
}

return string(data)
return data
}

// Take the application issue number and project name and turn it into
// a file path. This will always be unique because it is relying on
// github's issue numbers
// e.g. 782-foo.json
func (a *Application) FileName() string {
filename := fmt.Sprintf("%s-%s.json",
strconv.FormatInt(int64(a.IssueNumber), 10),
strings.ToLower(a.Project.Name),
)

filename = strings.ReplaceAll(strings.ToLower(filename), " ", "-")
filename = regexp.MustCompile(`[^\w.-]`).ReplaceAllString(filename, "")
filename = regexp.MustCompile(`-+`).ReplaceAllString(filename, "-")

return filename
}

func (a *Application) SetApprover() error {
if isTestingIssue() {
a.ApproverId = 123
a.ApproverUsername = "test-username"

return nil
}

approverIdValue, err := getEnv("APPROVER_ID")
if err != nil {
return err
}

approverId, err := strconv.Atoi(approverIdValue)
if err != nil {
return err
}

approverUsername, err := getEnv("APPROVER_USERNAME")
if err != nil {
return err
}

a.ApproverId = approverId
a.ApproverUsername = approverUsername

return nil
}

// Take the Markdown-format body of an issue and break it down by section header
Expand Down
102 changes: 102 additions & 0 deletions script/approver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package main

import (
"fmt"
"log"
"path/filepath"
"strings"
)

type Approver struct {
gitHub GitHub
application Application
}

func (a *Approver) Approve() {
a.gitHub = GitHub{}
a.application = Application{}

if err := a.application.SetApprover(); err != nil {
a.printErrorAndExit(err)
}

if err := a.gitHub.Init(); err != nil {
a.printErrorAndExit(err)
}

if *a.gitHub.Issue.State == "closed" {
a.printErrorAndExit(fmt.Errorf("script run on closed issue"))
}

if !a.gitHub.IssueHasLabel(LabelStatusApproved) {
a.printErrorAndExit(
fmt.Errorf("script run on issue that does not have required '%s' label", LabelStatusApproved),
)
}

a.application.Parse(a.gitHub.Issue)

if !a.application.IsValid() {
a.printErrorAndExit(
fmt.Errorf("script run on issue with invalid application data:\n\n%s", a.renderProblems()),
)
}

// The reviewer may remove this label themselves, but
// let's double check and remove it if they haven't
if a.gitHub.IssueHasLabel(LabelStatusReviewing) {
if err := a.gitHub.RemoveIssueLabel(LabelStatusReviewing); err != nil {
a.printErrorAndExit(
fmt.Errorf("could not remove issue label '%s': %s", LabelStatusReviewing, err.Error()),
)
}
}

if err := a.gitHub.CommitNewFile(
filepath.Join("data", a.application.FileName()),
a.application.GetData(),
fmt.Sprintf("Added \"%s\" to program", a.application.Project.Name),
); err != nil {
a.printErrorAndExit(
fmt.Errorf("could not create commit: %s", err.Error()),
)
}

if err := a.gitHub.CreateIssueComment(a.getApprovalMessage()); err != nil {
a.printErrorAndExit(
fmt.Errorf("could not create issue comment: %s", err.Error()),
)
}

if err := a.gitHub.CloseIssue(); err != nil {
a.printErrorAndExit(
fmt.Errorf("could not close issue: %s", err.Error()),
)
}
}

func (a *Approver) printErrorAndExit(err error) {
log.Fatalf("Error approving application: %s\n", err.Error())
}

func (a *Approver) renderProblems() string {
var problemStrings []string

for _, err := range a.application.Problems {
problemStrings = append(problemStrings, fmt.Sprintf("- %s", err.Error()))
}

return strings.Join(problemStrings, "\n")
}

func (a *Approver) getApprovalMessage() string {
return strings.TrimSpace(fmt.Sprintf(`### 🎉 Your application has been approved
Congratulations, @%s has approved your application! A promotion will be applied to your 1Password account shortly.
If you haven't done so already, we highly recommend implementing a [recovery plan for your team](https://support.1password.com/team-recovery-plan/) in case access for a particular contributor is ever lost. You may add additional core contributors as you see fit.
Finally, we'd love to hear more about your experience using 1Password in your development workflows! Feel free to join us over on the [1Password Developers Slack](https://join.slack.com/t/1password-devs/shared_invite/zt-15k6lhima-GRb5Ga~fo7mjS9xPzDaF2A) workspace.
Welcome to the program and happy coding! 🧑‍💻`, a.application.ApproverUsername))
}
5 changes: 4 additions & 1 deletion script/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
)

func printUsageAndExit() {
log.Fatalf("Usage: ./processor <review> [--test-issue <issue name>]")
log.Fatalf("Usage: ./processor <review|approve> [--test-issue <issue name>]")
}

func getEnv(key string) (string, error) {
Expand Down Expand Up @@ -38,6 +38,9 @@ func main() {
case "review":
reviewer := Reviewer{}
reviewer.Review()
case "approve":
approver := Approver{}
approver.Approve()
default:
fmt.Printf("Invalid command: %s\n", command)
printUsageAndExit()
Expand Down
60 changes: 60 additions & 0 deletions script/test-issues/valid-project-approved.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:%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-closed.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"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"
},
"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"
}

0 comments on commit c3d9a0c

Please sign in to comment.