Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to exclude workflow initiator (GITHUB_ACTOR) as an approver #59

Merged
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ steps:
approvers: user1,user2,org-team1
minimum-approvals: 1
issue-title: "Deploying v1.3.5 to prod from staging"
exclude-workflow-initiator-as-approver: false
```

- `approvers` is a comma-delimited list of all required approvers. An approver can either be a user or an org team. (*Note: Required approvers must have the ability to be set as approvers in the repository. If you add an approver that doesn't have this permission then you would receive an HTTP/402 Validation Failed error when running this action*)
- `minimum-approvals` is an integer that sets the minimum number of approvals required to progress the workflow. Defaults to ALL approvers.
- `issue-title` is a string that will be appened to the title of the issue.
- `issue-title` is a string that will be appended to the title of the issue.
- `exclude-workflow-initiator-as-approver` is a boolean that indicates if the workflow initiator (determined by the `GITHUB_ACTOR` environment variable) should be filtered from the final list of approvers. This is optional and defaults to `false`. Set this to `true` to prevent users in the `approvers` list from being able to self-approve workflows.

## Org team approver

Expand Down
3 changes: 3 additions & 0 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ inputs:
issue-title:
description: The custom subtitle for the issue
required: false
exclude-workflow-initiator-as-approver:
description: Whether or not to filter out the user who initiated the workflow as an approver if they are in the approvers list
default: false
runs:
using: docker
image: docker://ghcr.io/trstringer/manual-approval:1.7.0
25 changes: 19 additions & 6 deletions approvers.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,27 @@ import (
)

func retrieveApprovers(client *github.Client, repoOwner string) ([]string, error) {
approvers := []string{}
workflowInitiator := os.Getenv(envVarWorkflowInitiator)
shouldExcludeWorkflowInitiatorRaw := os.Getenv(envVarExcludeWorkflowInitiatorAsApprover)
shouldExcludeWorkflowInitiator, parseBoolErr := strconv.ParseBool(shouldExcludeWorkflowInitiatorRaw)
if parseBoolErr != nil {
return nil, fmt.Errorf("error parsing exclude-workflow-initiator-as-approver flag: %w", parseBoolErr)
}

approvers := []string{}
requiredApproversRaw := os.Getenv(envVarApprovers)
requiredApprovers := strings.Split(requiredApproversRaw, ",")

for i := range requiredApprovers {
requiredApprovers[i] = strings.TrimSpace(requiredApprovers[i])
requiredApprovers[i] = strings.TrimSpace(requiredApprovers[i])
}

for _, approverUser := range requiredApprovers {
expandedUsers := expandGroupFromUser(client, repoOwner, approverUser)
expandedUsers := expandGroupFromUser(client, repoOwner, approverUser, workflowInitiator, shouldExcludeWorkflowInitiator)
if expandedUsers != nil {
approvers = append(approvers, expandedUsers...)
} else if strings.EqualFold(workflowInitiator, approverUser) && shouldExcludeWorkflowInitiator {
fmt.Printf("Not adding user '%s' as an approver as they are the workflow initiator\n", approverUser)
} else {
approvers = append(approvers, approverUser)
}
Expand All @@ -48,7 +56,7 @@ func retrieveApprovers(client *github.Client, repoOwner string) ([]string, error
return approvers, nil
}

func expandGroupFromUser(client *github.Client, org, userOrTeam string) []string {
func expandGroupFromUser(client *github.Client, org, userOrTeam string, workflowInitiator string, shouldExcludeWorkflowInitiator bool) []string {
fmt.Printf("Attempting to expand user %s/%s as a group (may not succeed)\n", org, userOrTeam)
users, _, err := client.Teams.ListTeamMembersBySlug(context.Background(), org, userOrTeam, &github.TeamListTeamMembersOptions{})
if err != nil {
Expand All @@ -58,7 +66,12 @@ func expandGroupFromUser(client *github.Client, org, userOrTeam string) []string

userNames := make([]string, 0, len(users))
for _, user := range users {
userNames = append(userNames, user.GetLogin())
userName := user.GetLogin()
if strings.EqualFold(userName, workflowInitiator) && shouldExcludeWorkflowInitiator {
fmt.Printf("Not adding user '%s' from group '%s' as an approver as they are the workflow initiator\n", userName, userOrTeam)
} else {
userNames = append(userNames, userName)
}
}

return userNames
Expand Down
16 changes: 9 additions & 7 deletions constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import "time"
const (
pollingInterval time.Duration = 10 * time.Second

envVarRepoFullName string = "GITHUB_REPOSITORY"
envVarRunID string = "GITHUB_RUN_ID"
envVarRepoOwner string = "GITHUB_REPOSITORY_OWNER"
envVarToken string = "INPUT_SECRET"
envVarApprovers string = "INPUT_APPROVERS"
envVarMinimumApprovals string = "INPUT_MINIMUM-APPROVALS"
envVarIssueTitle string = "INPUT_ISSUE-TITLE"
envVarRepoFullName string = "GITHUB_REPOSITORY"
envVarRunID string = "GITHUB_RUN_ID"
envVarRepoOwner string = "GITHUB_REPOSITORY_OWNER"
envVarWorkflowInitiator string = "GITHUB_ACTOR"
envVarToken string = "INPUT_SECRET"
envVarApprovers string = "INPUT_APPROVERS"
envVarMinimumApprovals string = "INPUT_MINIMUM-APPROVALS"
envVarIssueTitle string = "INPUT_ISSUE-TITLE"
envVarExcludeWorkflowInitiatorAsApprover string = "INPUT_EXCLUDE-WORKFLOW-INITIATOR-AS-APPROVER"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func newGithubClient(ctx context.Context) (*github.Client, error) {
apiUrl, apiUrlPresent := os.LookupEnv("GITHUB_API_URL")

if serverUrlPresent {
if ! apiUrlPresent {
if !apiUrlPresent {
apiUrl = serverUrl
}
return github.NewEnterpriseClient(apiUrl, serverUrl, tc)
Expand Down