Skip to content

Commit

Permalink
Add create & close milestone and bind issue to milestone support (#39)
Browse files Browse the repository at this point in the history
* Add create & close milestone and bind issue to milestone support (#37)

* Add create & close milestone and bind issue to milestone support

* Add create and close workflow

* fix: Fix close issue action
  • Loading branch information
hustcer authored Oct 19, 2024
1 parent 83a222e commit 3623f59
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 10 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/close.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Description:
# - Close a milestone by title or number.

name: Milestone Close@develop
on:
workflow_dispatch:
inputs:
milestone:
required: true
description: 'Title / Number'

# Fix GraphQL: Resource not accessible by integration (updatePullRequest)
permissions:
contents: write

jobs:
close-milestone:
runs-on: ubuntu-latest
name: Milestone Crete
steps:
- name: Close Milestone
uses: hustcer/milestone-action@develop
with:
action: close
github-token: ${{ secrets.PAT }}
milestone: ${{ github.event.inputs.milestone }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36 changes: 36 additions & 0 deletions .github/workflows/create.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Description:
# - Create a milestone by title, description and due date.

name: Milestone Create@develop
on:
workflow_dispatch:
inputs:
title:
required: true
description: 'Milestone Title'
description:
required: false
description: 'Milestone Description'
due-on:
required: false
description: 'Milestone Due Date'

# Fix GraphQL: Resource not accessible by integration (updatePullRequest)
permissions:
contents: write

jobs:
create-milestone:
runs-on: ubuntu-latest
name: Milestone Crete
steps:
- name: Create Milestone
uses: hustcer/milestone-action@develop
with:
action: create
github-token: ${{ secrets.PAT }}
title: ${{ github.event.inputs.title }}
due-on: ${{ github.event.inputs.due-on }}
description: ${{ github.event.inputs.description }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25 changes: 24 additions & 1 deletion action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ branding:
color: 'purple'

inputs:
action:
required: false
default: 'bind-pr'
description: 'The action to perform, should be bind-pr,bind-issue,create or close. Defaults to bind-pr.'
title:
required: false
default: '1.0.0'
description: 'The title of the milestone to create.'
description:
required: false
default: 'The first milestone.'
description: 'The description of the milestone to create.'
due-on:
required: false
default: ''
description: 'The due date of the milestone to create.'
force:
required: false
default: false
Expand All @@ -50,9 +66,16 @@ runs:
run: |
use ${{ github.action_path }}/nu/milestone.nu *
let repo = '${{ github.repository }}'
let action = '${{ inputs.action }}'
let title = '${{ inputs.title }}'
let description = '${{ inputs.description }}'
let due-on = '${{ inputs.due-on }}'
let token = '${{ inputs.github-token }}'
let issue = '${{ github.event.issue.number }}'
let pr = '${{ github.event.pull_request.number }}'
let force = '${{ inputs.force }}' | into bool
let milestone = '${{ inputs.milestone }}'
milestone-update $repo --gh-token $token --pr $pr --force=$force --milestone=$milestone
let commonArgs = [$action $repo --gh-token $token --force=$force]
let createArgs = [--title=$title --description=$description --due-on=$due-on]
milestone-action ...$commonArgs ...$createArgs --pr=$pr --issue=$issue --milestone=$milestone
80 changes: 71 additions & 9 deletions nu/milestone.nu
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
# [x] Support Windows, macOS, Linux
# [x] Should run on local machine or Github runners
# [x] Support dry run mode
# [ ] Create milestone by title, due_on, and description
# [ ] Close milestone by title or number
# [ ] Add milestone to issue that has been fixed by a PR
# [x] Create milestone by title, due_on, and description
# [x] Close milestone by title or number
# [x] Add milestone to issue that has been fixed by a PR
# Description: Scripts for Github milestone management.

use common.nu [ECODE, hr-line is-installed]
Expand All @@ -17,7 +17,8 @@ export-env {
$env.config.color_config.leading_trailing_space_bg = { attr: n }
}

export def 'milestone-update' [
# Bind milestone to a merged PR.
export def 'milestone-bind-for-pr' [
repo: string, # Github repository name
--gh-token(-t): string, # Github access token
--milestone(-m): string, # Milestone name
Expand All @@ -27,14 +28,14 @@ export def 'milestone-update' [
] {
check-gh
if ($gh_token | is-not-empty) { $env.GH_TOKEN = $gh_token }
let IGNORED_PR_STATUS = [CLOSED OPEN]
# Could be MERGED, OPEN, CLOSED.
let IGNORED_PR_STATUS = [CLOSED]
# PR state Could be MERGED, OPEN, CLOSED.
let prState = gh pr view $pr --repo $repo --json 'state' | from json | get state
if ($prState in $IGNORED_PR_STATUS) {
print $'PR (ansi p)($pr)(ansi reset) is in state (ansi p)($prState)(ansi reset), will be ignored.'
return
}
let selected = if ($milestone | is-empty) { guess-milestone $repo $pr } else { $milestone }
let selected = if ($milestone | is-empty) { guess-milestone-for-pr $repo $pr } else { $milestone }
if $force {
let prevMilestone = gh pr view $pr --repo $repo --json 'milestone' | from json | get milestone?.title? | default '-'
let shouldRemove = $prevMilestone != $selected
Expand All @@ -53,8 +54,47 @@ export def 'milestone-update' [
}
}

# Bind milestone to a completed issue.
export def 'milestone-bind-for-issue' [
repo: string, # Github repository name
--gh-token(-t): string, # Github access token
--milestone(-m): string, # Milestone name
--issue: string, # The Issue number that we want to add milestone.
--force(-f), # Force update milestone even if the milestone is already set.
--dry-run(-d), # Dry run, only print the milestone that would be set.
] {
check-gh
if ($gh_token | is-not-empty) { $env.GH_TOKEN = $gh_token }
let IGNORED_ISSUE_STATUS = [OPEN]
# Issue state Could be OPEN, CLOSED(with stateReasons: COMPLETED, NOT_PLANNED, REOPENED).
let issueState = gh issue view $issue --repo $repo --json 'state' | from json | get state
let stateReason = gh issue view $issue --repo $repo --json 'stateReason' | from json | get stateReason
let shouldIgnore = ($issueState in $IGNORED_ISSUE_STATUS) or ($stateReason == 'NOT_PLANNED')
if $shouldIgnore {
print $'Issue (ansi p)($issue)(ansi reset) is Not (ansi p)COMPLETED(ansi reset), will be ignored.'
return
}
let selected = if ($milestone | is-empty) { guess-milestone-for-issue $repo $issue } else { $milestone }
if $force {
let prevMilestone = gh issue view $issue --repo $repo --json 'milestone' | from json | get milestone?.title? | default '-'
let shouldRemove = $prevMilestone != $selected
if $dry_run and $shouldRemove {
print $'(char nl)Would remove milestone for Issue (ansi p)($issue)(ansi reset) in repository (ansi p)($repo)(ansi reset) ...'
} else if $shouldRemove {
gh issue edit $issue --repo $repo --remove-milestone
} else {
print $'(char nl)Milestone for Issue (ansi p)($issue)(ansi reset) in repo (ansi p)($repo)(ansi reset) was already set to (ansi p)($prevMilestone)(ansi reset), will be ignored.'
}
}
print $'(char nl)Setting milestone to (ansi p)($selected)(ansi reset) for Issue (ansi p)($issue)(ansi reset) in repository (ansi p)($repo)(ansi reset) ...'
# FIXME: GraphQL: Resource not accessible by integration (updatePullRequest)
if not $dry_run {
gh issue edit $issue --repo $repo --milestone $selected
}
}

# Guess milestone by the merged date of the PR and the infomation of open milestones.
def guess-milestone [repo: string, pr: string] {
def guess-milestone-for-pr [repo: string, pr: string] {
# Query github open milestone list by gh
let milestones = gh api -X GET $'/repos/($repo)/milestones' --paginate | from json
| select number title due_on created_at html_url
Expand Down Expand Up @@ -153,4 +193,26 @@ def check-gh [] {
}
}

alias main = milestone-update
# Milestone action entry point.
export def milestone-action [
action: string, # Action to perform, could be create, close, or bind-pr.
repo: string, # Github repository name
--gh-token(-t): string, # Github access token
--milestone(-m): string, # Milestone name
--title: string, # Milestone title to create or close
--due-on(-d): string, # Milestone due date, format: yyyy/mm/dd
--description(-D): string,# Milestone description
--pr: string, # The PR number/url/branch of the PR that we want to add milestone.
--issue: string, # The Issue number that we want to add milestone.
--force(-f), # Force update milestone even if the milestone is already set.
--dry-run(-d), # Dry run, only print the milestone that would be set.
] {
match $action {
close => { close-milestone $repo $milestone --gh-token $gh_token },
create => { create-milestone $repo $title --due-on $due_on -D $description -t $gh_token },
bind-pr => { milestone-bind-for-pr $repo -t $gh_token -m $milestone --pr $pr --force=$force --dry-run=$dry_run },
bind-issue => { milestone-bind-for-issue $repo -t $gh_token -m $milestone --issue $issue --force=$force --dry-run=$dry_run },
}
}

alias main = milestone-action

0 comments on commit 3623f59

Please sign in to comment.