From 8fddbf58be07def24cb8b9c848e26d3c9b822c3d Mon Sep 17 00:00:00 2001 From: Javier Romero Date: Tue, 13 Jul 2021 18:30:56 +0000 Subject: [PATCH 1/2] Add Issues Generation as per RFC #0084 1. A GitHub Action that monitors PRs for the purpose of easier issue management: 1. Creates an initial comment instructing maintainers that is updated as issues are queued. 2. Parses comments for `/queue-issue` or `/unqueue-issue` to track issues to create. 2. A `node` based CLI to query and create queued issues (currently necessary to integrate with `merge-rfc.sh`) 3. Changes to `merge-rfc.sh` to query and create queued issues Signed-off-by: Javier Romero --- .github/workflows/issues-generation.yml | 24 ++++ merge-rfc.sh | 147 ++++++++++++++++++------ 2 files changed, 135 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/issues-generation.yml diff --git a/.github/workflows/issues-generation.yml b/.github/workflows/issues-generation.yml new file mode 100644 index 000000000..41d0b8128 --- /dev/null +++ b/.github/workflows/issues-generation.yml @@ -0,0 +1,24 @@ +name: Issues Generation + +concurrency: issues-generation + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + pull_request_target: + types: [opened, reopened] + +jobs: + issue-generation-bot: + if: ${{ github.event.issue.pull_request || github.event.pull_request }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Run Issue Generation + uses: jromero/issue-generation-action@v1.0.0-beta.2 + id: issues-generation + with: + github-token: ${{ secrets.LEARNING_GITHUB_TOKEN }} + bot-username: buildpack-bot diff --git a/merge-rfc.sh b/merge-rfc.sh index cfbe7698c..7d4da5e2e 100755 --- a/merge-rfc.sh +++ b/merge-rfc.sh @@ -1,41 +1,87 @@ -#!/usr/bin/env zsh +#!/usr/bin/env bash set -euo pipefail script="$0" + +#### +# CONFIG +# + +MAIN_BRANCH=${MAIN_BRANCH:-main} +OWNER=${OWNER:-buildpacks} +REPO=rfcs +BOT_USERNAME="buildpack-bot" + +#### +# FUNCTIONS +# + usage() { - printf "Usage: %s [-i ...] [-n] \n" "$script" + printf "Usage: %s [-i ...] [-n] \n" "$script" printf "Flags:\n" - printf " -i string\n\tgithub issue reference (example: buildpacks/spec#1)\n" - printf " -n\n\tno issues\n" + printf " -i string\n\tgithub issue reference (example: ${OWNER}/${REPO}#1)\n" + printf " -n\n\tbe okay with no issues being created\n" exit 1 } -id() { - ID=$(find text -depth 1 | sed -E 's|^text/([[:digit:]]{4})-.*$|\1|' | sort | tail -n 1) - ((ID++)) - printf "%04d" "${ID}" +generate_id() { + id="$(find text -maxdepth 1 -type f | sed -E 's|^text/([[:digit:]]{4})-.*$|\1|' | sort | tail -n 1 | sed 's/^0*//')" + ((id++)) + printf "%04d" "${id}" } link_issue() { local issue="$1" - link=$(echo "$issue" | sed -E 's|buildpacks/(.*)#([[:digit:]]+)|https://github.com/buildpacks/\1/issues/\2|') + link=$(echo "$issue" | sed -E "s|([^\/]+)/([^#]+)#([[:digit:]]+)$|https://github.com/\1/\2/issues/\3|") printf '[%s](%s)' "$issue" "$link" } -issues="N/A" -no_issues=false +require_command() { + if ! [ -x "$(command -v ${1})" ]; then + echo "Error: '${1}' is not installed." >&2 + exit 1 + fi +} + +#### +# DEPENDENCIES +# + +require_command git +require_command jq +require_command issues-generation + +if [[ -z "${GITHUB_TOKEN:-}" ]]; then + require_command op + echo "> Pulling GitHub token from vault..." + GITHUB_TOKEN=$(op get item 7xorpxvz3je3vozqg3fy3wrcg4 --vault "Shared" --account buildpacks | jq -r '.details.sections[] | select(.fields).fields[] | select(.t == "credential").v') +fi + +#### +# INPUTS / VALIDATION +# + +shift $(($OPTIND - 1)) +if [[ $# != 1 ]]; then + usage +fi + +PR_NUMBER="${1}" +NO_ISSUES=false +ISSUES_TEXT="N/A" + while getopts ":i:n" opt; do case ${opt} in i ) - if [[ $issues == "N/A" ]]; then - issues=$(link_issue "$OPTARG") + if [[ $ISSUES_TEXT == "N/A" ]]; then + ISSUES_TEXT=$(link_issue "$OPTARG") else - issues+=", $(link_issue "$OPTARG")" + ISSUES_TEXT+=", $(link_issue "$OPTARG")" fi ;; n ) - no_issues=true + NO_ISSUES=true ;; \? ) echo "Invalid option: $OPTARG" 1>&2 @@ -48,36 +94,65 @@ while getopts ":i:n" opt; do esac done -if [[ $no_issues = false && $issues == "N/A" ]]; then - echo -e "ERROR! No issues were provided. Are you sure there are no issues that should be linked?" - echo -e "ERROR! Either -i or -n is required\n" - usage +CURRENT_BRANCH=$(git branch --show-current) +if [[ "${CURRENT_BRANCH}" != "${MAIN_BRANCH}" ]]; then + echo -e "ERROR! Expected current branch to be '${MAIN_BRANCH}', currently in '${CURRENT_BRANCH}'!"; + exit 1; fi -shift $(($OPTIND - 1)) -if [[ $# != 1 ]]; then +#### +# TASK +# + +RFC_ID=$(generate_id) +echo "> Generated RFC number: ${RFC_ID}" + +echo "> Creating issues..." +export GITHUB_TOKEN + +issues-generation create --pr "${OWNER}/${REPO}#${PR_NUMBER}" --bot $BOT_USERNAME --prepend "[RFC #${RFC_ID}] " +ISSUES_TO_LINK=$(issues-generation list --pr "${OWNER}/${REPO}#${PR_NUMBER}" --bot $BOT_USERNAME --json | jq -r '[.[] | select(.num) | .repo + "#" + (.num|tostring) ] | join(" ")') + +for ISSUE in ${ISSUES_TO_LINK}; do + if [[ $ISSUES_TEXT == "N/A" ]]; then + ISSUES_TEXT=$(link_issue "$ISSUE") + else + ISSUES_TEXT+=", $(link_issue "$ISSUE")" + fi +done + + +if [[ $NO_ISSUES = false && $ISSUES_TEXT == "N/A" ]]; then + echo -e "ERROR! No issues were provided. Are you sure there are no issues that should be linked?" + echo -e "ERROR! Either -i or -n is required\n" usage fi +echo "> Pulling latest changes...." git pull origin --rebase -PR="${1}" -ID=$(id) +echo "> Merging PR#${PR_NUMBER} as rfc-${RFC_ID}" +git fetch origin "pull/${PR_NUMBER}/head:rfc-${RFC_ID}" +git merge "rfc-${RFC_ID}" --signoff --no-edit --no-ff +git branch -d "rfc-${RFC_ID}" -echo "Merging PR ${PR} as rfc-${ID}" +SOURCE_DOC=$(find text -maxdepth 1 -name '0000-*') +TARGET_DOC=${SOURCE_DOC//0000/${RFC_ID}} -git fetch origin "pull/${PR}/head:rfc-${ID}" -git merge "rfc-${ID}" --signoff --no-edit --no-ff -git branch -d "rfc-${ID}" +echo "> Updating document: ${SOURCE_DOC}" +SEDOPTION="-i" +if [[ "$OSTYPE" == "darwin"* ]]; then + SEDOPTION="-i ''" +fi +sed $SEDOPTION "s|- RFC Pull Request:.*|- RFC Pull Request: [${REPO}#${PR_NUMBER}](https://github.com/${OWNER}/${REPO}/pull/${PR_NUMBER})|" "${SOURCE_DOC}" +sed $SEDOPTION "s|- CNB Issue:.*|- CNB Issue: $ISSUES_TEXT|" "${SOURCE_DOC}" -SOURCE=$(find text -depth 1 -name '0000-*') -TARGET=${SOURCE//0000/$(printf "%04d" "${ID}")} +echo "> Moving ${SOURCE_DOC} to ${TARGET_DOC}..." +git mv "${SOURCE_DOC}" "${TARGET_DOC}" +git add "${TARGET_DOC}" -sed -i '' "s|- RFC Pull Request:.*|- RFC Pull Request: [rfcs#${PR}](https://github.com/buildpacks/rfcs/pull/${PR})|" "${SOURCE}" -sed -i '' "s|- CNB Issue:.*|- CNB Issue: $issues|" "${SOURCE}" -git mv "${SOURCE}" "${TARGET}" -git add "${TARGET}" -git commit --signoff --message "RFC ${ID} +echo "> Committing..." +git commit --signoff --message "RFC ${RFC_ID} -[#${PR}] -" +[#${PR_NUMBER}] +" \ No newline at end of file From ad5b5484c0d9fdd013061748695526166df75e5a Mon Sep 17 00:00:00 2001 From: Javier Romero Date: Tue, 13 Jul 2021 19:04:55 +0000 Subject: [PATCH 2/2] Bump action to v1.0.0-beta.3 Signed-off-by: Javier Romero --- .github/workflows/issues-generation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/issues-generation.yml b/.github/workflows/issues-generation.yml index 41d0b8128..29e145ece 100644 --- a/.github/workflows/issues-generation.yml +++ b/.github/workflows/issues-generation.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Run Issue Generation - uses: jromero/issue-generation-action@v1.0.0-beta.2 + uses: jromero/issue-generation-action@v1.0.0-beta.3 id: issues-generation with: github-token: ${{ secrets.LEARNING_GITHUB_TOKEN }}