-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add workflow to transfer issues from another mozilla repository (#1591)
* Add workflow to transfer issues from another mozilla repository * use PAT * Make script locally executable. Add ability to run for specific issue. * fix docs and typo in env variable * Add prefill link
- Loading branch information
Showing
2 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
name: Transfer issues | ||
|
||
# To run this action. You need to do the following: | ||
# | ||
# 1. Create a personal access token (Classic) with the `repo` and `read:org` scopes. | ||
# | ||
# URL: https://github.com/settings/tokens/new?description=transfer-issues-token&scopes=repo,read:org | ||
# | ||
# 2. Authorize the token for use with [SAML](https://github.com/latest/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on) on the `mozilla` org. | ||
# | ||
# 3. Create a secret in the repository with whatever name you want, and paste the token as the value. | ||
# | ||
# ex: $ gh secret set <secret-name> --body "<token_value> | ||
# | ||
# 4. Run the action with the secret name as the `secret_name` input. | ||
# | ||
# ex: `gh secret set <secret-name> --body "<token_value>" && gh workflow run 90730614 --field count="10" --field from_name="addons-server" --field secret_name="<secret-name>"` | ||
# | ||
# Note: you need to paste the PAT in body, so make sure to keep track of the value before saving it. | ||
# Also verify the workflow ID is correct. You can run without arguments and select interactively. | ||
# | ||
# Note: After each run this action purges the secret from the repo action secrets. | ||
# This prevents pollution or conflict. So you have to reset it every time. | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
count: | ||
description: How many issues to transfer | ||
default: "1" | ||
required: true | ||
issue_number: | ||
description: "the issue number to transfer. Overrides count if set." | ||
required: false | ||
from_name: | ||
description: "the name of the mozilla/<from_name repository to transfer issues from" | ||
required: true | ||
secret_name: | ||
description: "the name of the secret containing the PAT for the repository to transfer issues to" | ||
required: true | ||
|
||
permissions: write-all | ||
|
||
concurrency: | ||
group: transfer | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
fetch_issues: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Transfer issues | ||
env: | ||
ALLOWED_REPOS: "addons-server,addons-frontend" | ||
GH_TOKEN: ${{ secrets[format('{0}', inputs.secret_name)] }} | ||
FROM_NAME: ${{ inputs.from_name }} | ||
REPOSITORY_OWNER: ${{ github.repository_owner }} | ||
TO_NAME: ${{ github.event.repository.name }} | ||
COUNT: ${{ inputs.count }} | ||
ISSUE_NUMBER: ${{ inputs.issue_number }} | ||
shell: bash | ||
run: ./scripts/transfer-issues.sh | ||
|
||
- name: Delete secret | ||
if: always() | ||
shell: bash | ||
env: | ||
GH_TOKEN: ${{ secrets[format('{0}', inputs.secret_name)] }} | ||
run: | | ||
set -x | ||
if gh secret list --json name --jq '.[] | .name' | grep -q "${{ inputs.secret_name }}"; then | ||
gh secret delete ${{ inputs.secret_name }} | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
#!/bin/bash | ||
|
||
set -x | ||
|
||
COUNT=${COUNT:-1} | ||
ISSUE_NUMBER=${ISSUE_NUMBER:-} | ||
|
||
set -u | ||
|
||
# Required environment variables | ||
# GITHUB_TOKEN: GitHub token with repo scope | ||
# REPOSITORY_OWNER: GitHub repository owner | ||
# FROM_NAME: Repository name to transfer issues from | ||
# TO_NAME: Repository name to transfer issues to | ||
# ALLOWED_REPOS: Comma-separated list of allowed repositories | ||
|
||
# Optional environment variables | ||
# ISSUE_NUMBER: Issue number to transfer (will nullify COUNT) | ||
# COUNT: Number of issues to transfer | ||
|
||
FROM_REPO="$REPOSITORY_OWNER/$FROM_NAME" | ||
TO_REPO="$REPOSITORY_OWNER/$TO_NAME" | ||
|
||
echo """ | ||
REPOSITORY_OWNER: $REPOSITORY_OWNER | ||
FROM_NAME: $FROM_NAME | ||
TO_NAME: $TO_NAME | ||
ALLOWED_REPOS: $ALLOWED_REPOS | ||
FROM_REPO: $FROM_REPO | ||
TO_REPO: $TO_REPO | ||
ISSUE_NUMBER: $ISSUE_NUMBER | ||
COUNT: $COUNT | ||
""" | ||
|
||
auth_status=$(gh auth status 2>&1) | ||
|
||
if [[ "$auth_status" == *"You are not logged into any GitHub hosts."* ]]; then | ||
echo "Error: $auth_status" | ||
exit 1 | ||
fi | ||
|
||
if [[ ! "$ALLOWED_REPOS" =~ (^|,)"$FROM_NAME"(,|$) ]]; then | ||
echo "Invalid FROM_NAME "$FROM_NAME". Exiting..." | ||
exit 1 | ||
fi | ||
|
||
function get_single_issue() { | ||
local issues_query=""" | ||
query { | ||
repository(owner: \"$REPOSITORY_OWNER\", name: \"$FROM_NAME\") { | ||
issue(number: $ISSUE_NUMBER) { | ||
id | ||
} | ||
} | ||
} | ||
""" | ||
|
||
local issues=$(gh api graphql -f query="$issues_query" --jq '.data.repository.issue.id') | ||
|
||
echo "$issues" | ||
} | ||
|
||
function get_multiple_issues() { | ||
local issues_query=""" | ||
query { | ||
repository(owner: \"$REPOSITORY_OWNER\", name: \"$FROM_NAME\") { | ||
issues(first: $COUNT, orderBy: {field: CREATED_AT, direction: ASC}) { | ||
nodes { | ||
id | ||
} | ||
} | ||
} | ||
} | ||
""" | ||
|
||
local issues=$(gh api graphql -f query="$issues_query" --jq '.data.repository.issues.nodes[].id') | ||
|
||
echo "$issues" | ||
} | ||
|
||
if [[ -n "$ISSUE_NUMBER" ]]; then | ||
echo "Transferring issue $ISSUE_NUMBER from \"$FROM_REPO\" to \"$TO_REPO\"" | ||
issues=$(get_single_issue) | ||
else | ||
echo "Transferring $COUNT issues from \"$FROM_REPO\" to \"$TO_REPO\"" | ||
issues=$(get_multiple_issues) | ||
fi | ||
|
||
transfer_mutation="mutation {" | ||
|
||
new_issues_counter=1 | ||
|
||
repository_id=$(gh repo view "$TO_REPO" --json id --jq '.id') | ||
|
||
while IFS= read -r issue_id; do | ||
transfer_mutation+=" t${new_issues_counter}: transferIssue(input: { issueId: \"${issue_id}\", repositoryId: \"${repository_id}\", createLabelsIfMissing: true }) { issue { id url } }" | ||
new_issues_counter=$((new_issues_counter+1)) | ||
done <<< "$issues" | ||
|
||
transfer_mutation+=" }" | ||
|
||
new_issues=$(gh api graphql -f query="$transfer_mutation" --jq '.data | keys[] as $k | {url: .[$k].issue.url, id: .[$k].issue.id}') | ||
|
||
repo_label="repository:$FROM_NAME" | ||
|
||
gh label create \"$repo_label\" -R "$TO_REPO" --force | ||
|
||
label_id=$(gh api /repos/$TO_REPO/labels/$repo_label --jq '.node_id') | ||
|
||
label_mutation="mutation {" | ||
|
||
label_counter=1 | ||
|
||
while IFS= read -r id; do | ||
label_mutation+=" l${label_counter}: updateIssue(input: {id: \"$id\", labelIds: [\"$label_id\"]}) { __typename }" | ||
label_counter=$((label_counter+1)) | ||
done <<< $(echo "$new_issues" | jq -r '.id') | ||
|
||
label_mutation+=" }" | ||
|
||
gh api graphql -f query="$label_mutation" | ||
|
||
echo "$new_issues" | jq -r '.url' |