Skip to content

Commit

Permalink
Feature: Allow Custom Approval or Denial Words (#66)
Browse files Browse the repository at this point in the history
* Add support for custom approval and denial words

* Work out some regex nuances with GitHub
  • Loading branch information
Bwvolleyball authored Feb 17, 2023
1 parent 948dfe9 commit 639442a
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 83 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.env
.idea/
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,22 @@ steps:
issue-title: "Deploying v1.3.5 to prod from staging"
issue-body: "Please approve or deny the deployment of version v1.3.5."
exclude-workflow-initiator-as-approver: false
additional-approved-words: ''
additional-denied-words: ''
```
- `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 appended to the title of the issue.
- `issue-body` is a string that will be prepended to the body 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.
- `additional-approved-words` is a comma separated list of strings to expand the dictionary of words that indicate approval. This is optional and defaults to an empty string.
- `additional-denied-words` is a comma separated list of strings to expand the dictionary of words that indicate denial. This is optional and defaults to an empty string.

### Using Custom Words

GitHub has a rich library of emojis, and these all work in additional approved words or denied words. Some values GitHub will store in their text version - i.e. `:shipit:`. Other emojis, GitHub will store in their unicode emoji form, like ✅.
For a seamless experience, it is recommended that you add the custom words to a GitHub comment, and then copy it back out of the comment into your actions configuration yaml.

## Org team approver

Expand Down
6 changes: 6 additions & 0 deletions action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ inputs:
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
additional-approved-words:
description: Comma separated list of words that can be used to approve beyond the defaults.
default: ''
additional-denied-words:
description: Comma separated list of words that can be used to deny beyond the defaults.
default: ''
runs:
using: docker
image: docker://ghcr.io/trstringer/manual-approval:1.8.0
10 changes: 8 additions & 2 deletions approval.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,14 @@ func approversIndex(approvers []string, name string) int {

func isApproved(commentBody string) (bool, error) {
for _, approvedWord := range approvedWords {
matched, err := regexp.MatchString(fmt.Sprintf("(?i)^%s[.!]*\n*$", approvedWord), commentBody)
re, err := regexp.Compile(fmt.Sprintf("(?i)^%s[.!]*\n*\\s*$", approvedWord))
if err != nil {
fmt.Printf("Error parsing. %v", err)
return false, err
}

matched := re.MatchString(commentBody)

if matched {
return true, nil
}
Expand All @@ -159,10 +163,12 @@ func isApproved(commentBody string) (bool, error) {

func isDenied(commentBody string) (bool, error) {
for _, deniedWord := range deniedWords {
matched, err := regexp.MatchString(fmt.Sprintf("(?i)^%s[.!]*\n*$", deniedWord), commentBody)
re, err := regexp.Compile(fmt.Sprintf("(?i)^%s[.!]*\n*\\s*$", deniedWord))
if err != nil {
fmt.Printf("Error parsing. %v", err)
return false, err
}
matched := re.MatchString(commentBody)
if matched {
return true, nil
}
Expand Down
Loading

0 comments on commit 639442a

Please sign in to comment.