From ae299fcfd7c6008108b36f1c85e1d0091149490d Mon Sep 17 00:00:00 2001 From: Subeom Choi Date: Fri, 26 Apr 2024 02:12:19 +0900 Subject: [PATCH 1/3] feature: add customizable feature (#2) * feature: add customizable feature * fix: support self repository --- .github/workflows/gitflow.yml | 191 +++++++++++++++++++++++----------- changelog.md | 4 + readme.md | 37 ++++--- 3 files changed, 159 insertions(+), 73 deletions(-) diff --git a/.github/workflows/gitflow.yml b/.github/workflows/gitflow.yml index fc7ef6d..190d17e 100644 --- a/.github/workflows/gitflow.yml +++ b/.github/workflows/gitflow.yml @@ -11,12 +11,61 @@ on: - main - develop workflow_call: + inputs: + MAIN_BRANCH: + description: 'Name of main branch' + type: string + default: 'main' + required: false + DEVELOP_BRANCH: + description: 'Name of develop branch' + type: string + default: 'develop' + required: false + FEATURE_BRANCHES: + description: 'Names of feature branch (seperator is " ")' + type: string + default: 'feature refactor fix change update document test chore' + required: false + RELEASE_BRANCHES: + description: 'Names of release branch (seperator is " ")' + type: string + default: 'release hotfix' + required: false + NORELEASE_BRANCHES: + description: 'Names of norelease branch (seperator is " ")' + type: string + default: 'norelease' + required: false + VERSION_EXPRESSION: + description: 'Regular expression of version on changelog' + type: string + default: '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*' + required: false + VERSION_HEADER: + description: 'Header of version on changelog' + type: string + default: '## ' + required: false + CHANGELOG: + description: 'Name of changelog file' + type: string + default: 'changelog.md' + required: false secrets: TOKEN: description: 'GitHub token (Default: GitHub Action token)' required: false env: + MAIN_BRANCH: ${{ inputs.MAIN_BRANCH || 'main' }} + DEVELOP_BRANCH: ${{ inputs.DEVELOP_BRANCH || 'develop' }} + FEATURE_BRANCHES: ${{ inputs.FEATURE_BRANCHES || 'feature refactor fix change update document test chore' }} + RELEASE_BRANCHES: ${{ inputs.RELEASE_BRANCHES || 'release hotfix' }} + NORELEASE_BRANCHES: ${{ inputs.NORELEASE_BRANCHES || 'norelease' }} + VERSION_EXPRESSION: ${{ inputs.VERSION_EXPRESSION || '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*' }} + VERSION_HEADER: ${{ inputs.VERSION_HEADER || '## ' }} + CHANGELOG: ${{ inputs.CHANGELOG || 'changelog.md' }} GITHUB_TOKEN: ${{ secrets.TOKEN || github.token }} SOURCE_BRANCH: ${{ github.event.pull_request.head.ref }} SOURCE_COMMIT: ${{ github.event.pull_request.head.sha }} @@ -30,40 +79,54 @@ jobs: - name: Check branch id: check-branch run: | - if [[ ${{ - ( - startsWith(env.SOURCE_BRANCH, 'feature/') - || startsWith(env.SOURCE_BRANCH, 'refactor/') - || startsWith(env.SOURCE_BRANCH, 'fix/') - || startsWith(env.SOURCE_BRANCH, 'change/') - || startsWith(env.SOURCE_BRANCH, 'update/') - || startsWith(env.SOURCE_BRANCH, 'document/') - || startsWith(env.SOURCE_BRANCH, 'test/') - ) - && env.DESTINATION_BRANCH == 'develop' - }} == true ]]; then + if [[ $( + if [[ '${{ env.DESTINATION_BRANCH }}' != '${{ env.DEVELOP_BRANCH }}' ]]; then + echo 'false' + fi + for FEATURE_BRANCH in $(echo '${{ env.FEATURE_BRANCHES }}'); do + if [[ '${{ env.SOURCE_BRANCH }}' =~ ^"$FEATURE_BRANCH"/.*$ ]]; then + echo 'true' + fi + done + ) == true ]]; then echo 'type=feature' >> $GITHUB_OUTPUT - elif [[ ${{ - ( - startsWith(env.SOURCE_BRANCH, 'release/') - || startsWith(env.SOURCE_BRANCH, 'hotfix/') - ) - && env.DESTINATION_BRANCH == 'main' - }} == true ]]; then + elif [[ $( + if [[ '${{ env.DESTINATION_BRANCH }}' != '${{ env.MAIN_BRANCH }}' ]]; then + echo 'false' + fi + for RELEASE_BRANCH in $(echo '${{ env.RELEASE_BRANCHES }}'); do + if [[ '${{ env.SOURCE_BRANCH }}' =~ ^"$RELEASE_BRANCH"/.*$ ]]; then + echo 'true' + fi + done + ) == true ]]; then echo 'type=release' >> $GITHUB_OUTPUT - elif [[ ${{ - startsWith(env.SOURCE_BRANCH, 'unrelease/') - && env.DESTINATION_BRANCH == 'main' - }} == true ]]; then - echo 'type=unrelease' >> $GITHUB_OUTPUT - elif [[ ${{ - ( - startsWith(env.SOURCE_BRANCH, 'release/') - || startsWith(env.SOURCE_BRANCH, 'hotfix/') - || startsWith(env.SOURCE_BRANCH, 'unrelease/') - ) - && env.DESTINATION_BRANCH == 'develop' - }} == true ]]; then + elif [[ $( + if [[ '${{ env.DESTINATION_BRANCH }}' != '${{ env.MAIN_BRANCH }}' ]]; then + echo 'false' + fi + for NORELEASE_BRANCH in $(echo '${{ env.NORELEASE_BRANCHES }}'); do + if [[ '${{ env.SOURCE_BRANCH }}' =~ ^"$NORELEASE_BRANCH"/.*$ ]]; then + echo 'true' + fi + done + ) == true ]]; then + echo 'type=norelease' >> $GITHUB_OUTPUT + elif [[ $( + if [[ '${{ env.DESTINATION_BRANCH }}' != '${{ env.DEVELOP_BRANCH }}' ]]; then + echo 'false' + fi + for RELEASE_BRANCH in $(echo '${{ env.RELEASE_BRANCHES }}'); do + if [[ '${{ env.SOURCE_BRANCH }}' =~ ^"$RELEASE_BRANCH"/.*$ ]]; then + echo 'true' + fi + done + for NORELEASE_BRANCH in $(echo '${{ env.NORELEASE_BRANCHES }}'); do + if [[ '${{ env.SOURCE_BRANCH }}' =~ ^"$NORELEASE_BRANCH"/.*$ ]]; then + echo 'true' + fi + done + ) == true ]]; then echo 'type=update' >> $GITHUB_OUTPUT else exit 1 @@ -76,9 +139,9 @@ jobs: script: | const message = [ 'Invalid pull request: ', - 'only (release/ or hotfix/ => main) ', - 'or (unrelease/ => main) ', - 'or (feature/ or refactor/ or fix/ or change/ or update/ or document/ or test/ => develop) is allowed', + 'only ({RELEASE_TYPE}/ => ${{ env.MAIN_BRANCH }}) ', + 'or ({NORELEASE_TYPE}/ => ${{ env.MAIN_BRANCH }}) ', + 'or ({FEATURE_TYPE}/ => ${{ env.DEVELOP_BRANCH }}) is allowed', ].join('') github.rest.issues.createComment({ issue_number: context.issue.number, @@ -111,8 +174,8 @@ jobs: && steps.check-branch.outcome == 'success' && steps.check-branch.outputs.type == 'feature' run: | - cat changelog.md \ - | grep '^## Unreleased$' \ + cat ${{ env.CHANGELOG }} \ + | grep '^${{ env.VERSION_HEADER }}Unreleased$' \ || (echo 'failure=changelog-not-contains-unreleased' >> $GITHUB_OUTPUT; exit 1) git diff --name-only ${{ env.DESTINATION_COMMIT }} \ | grep --perl-regexp 'changelog\.md' \ @@ -125,7 +188,11 @@ jobs: script: | const message = (() => { if ('${{ steps.check-feature-branch.outputs.failure }}' === 'changelog-not-contains-unreleased') { - return `Invalid pull request: '## Unreleased' should be existed on changelog.md` + return [ + `Invalid pull request: `, + `'${{ env.VERSION_HEADER }}Unreleased' `, + `should be existed on ${{ env.CHANGELOG }}.`, + ].join('') } })() github.rest.issues.createComment({ @@ -149,7 +216,7 @@ jobs: script: | const message = (() => { if ('${{ steps.check-feature-branch.outputs.warning }}' === 'changelog-not-modified') { - return `I recommend that you should modify changelog.md.` + return `I recommend that you should modify ${{ env.CHANGELOG }}.` } })() github.rest.issues.createComment({ @@ -169,21 +236,21 @@ jobs: run: | VERSION=$( echo '${{ env.SOURCE_BRANCH }}' \ - | grep '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*' --only-matching + | grep '${{ env.VERSION_EXPRESSION }}' --only-matching ) \ && (echo "version=$VERSION" >> $GITHUB_OUTPUT) \ || (echo 'failure=version-not-found' >> $GITHUB_OUTPUT; exit 1) - cat changelog.md \ - | grep '^## Unreleased$' \ + cat ${{ env.CHANGELOG }} \ + | grep '^${{ env.VERSION_HEADER }}Unreleased$' \ && (echo 'failure=changelog-contains-unreleased' >> $GITHUB_OUTPUT; exit 1) \ || : - cat changelog.md \ - | grep "^## $VERSION$" \ + cat ${{ env.CHANGELOG }} \ + | grep "^${{ env.VERSION_HEADER }}$VERSION$" \ || (echo 'failure=changelog-not-contains-version' >> $GITHUB_OUTPUT; exit 1) CHANGELOG=$( - cat changelog.md \ - | perl -0pe "s/(.*\n)*## $VERSION\n//g" \ - | perl -0pe 's/(\n?)## .*\n(.*\n)*/\1/g' \ + cat ${{ env.CHANGELOG }} \ + | perl -0pe "s/(.*\n)*${{ env.VERSION_HEADER }}$VERSION\n//g" \ + | perl -0pe 's/(\n?)${{ env.VERSION_HEADER }}.*\n(.*\n)*/\1/g' \ | perl -0pe 's/^\n*//g' \ | perl -0pe 's/\n*$//g' ) \ @@ -197,17 +264,25 @@ jobs: script: | const message = (() => { if ('${{ steps.check-release-branch.outputs.failure }}' === 'version-not-found') { - return `Invalid pull request: source branch should satisfy 'type/0.0.0' format` + return `Invalid pull request: source branch should satisfy '{RELEASE_TYPE}/0.0.0' format.` } else if ('${{ steps.check-release-branch.outputs.failure }}' === 'changelog-contains-unreleased') { - return `Invalid pull request: '## Unreleased' should not be existed on changelog.md` + return [ + `Invalid pull request: `, + `'${{ env.VERSION_HEADER }}Unreleased' `, + `should not be existed on ${{ env.CHANGELOG }}.`, + ].join('') } else if ('${{ steps.check-release-branch.outputs.failure }}' === 'changelog-not-contains-version') { const version = '${{ steps.check-release-branch.outputs.version }}' - return `Invalid pull request: '## ${version}' should be existed on changelog.md` + return [ + `Invalid pull request: `, + `'${{ env.VERSION_HEADER }}${version}' `, + `should not be existed on ${{ env.CHANGELOG }}.`, + ].join('') } else if ('${{ steps.check-release-branch.outputs.failure }}' === 'changelog-is-empty') { - return `Invalid pull request: changelog is empty` + return `Invalid pull request: changelog is empty.` } })() github.rest.issues.createComment({ @@ -243,12 +318,12 @@ jobs: run: | VERSION=$( echo '${{ env.SOURCE_BRANCH }}' \ - | grep '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*' --only-matching + | grep '${{ env.VERSION_EXPRESSION }}' --only-matching ) CHANGELOG=$( - cat changelog.md \ - | perl -0pe "s/(.*\n)*## $VERSION\n//g" \ - | perl -0pe 's/(\n?)## .*\n(.*\n)*/\1/g' \ + cat ${{ env.CHANGELOG }} \ + | perl -0pe "s/(.*\n)*${{ env.VERSION_HEADER }}$VERSION\n//g" \ + | perl -0pe 's/(\n?)${{ env.VERSION_HEADER }}.*\n(.*\n)*/\1/g' \ | perl -0pe 's/^\n*//g' \ | perl -0pe 's/\n*$//g' ) @@ -275,12 +350,12 @@ jobs: && git push origin --delete ${{ env.SOURCE_BRANCH }} \ || : - - name: Finish unrelease branch - id: finish-unrelease-branch + - name: Finish norelease branch + id: finish-norelease-branch if: | github.event.pull_request.merged == true && steps.check-branch.outcome == 'success' - && steps.check-branch.outputs.type == 'unrelease' + && steps.check-branch.outputs.type == 'norelease' run: | git checkout -b '${{ env.SOURCE_BRANCH }}' '${{ env.SOURCE_COMMIT }}' \ && git push -u origin '${{ env.SOURCE_BRANCH }}' \ diff --git a/changelog.md b/changelog.md index 6b27954..bbcb022 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,7 @@ +## Unreleased + +- feature: add customizable feature. + ## 2.0.0 - change: make gitflow as reusable workflow diff --git a/readme.md b/readme.md index 2da15c4..1cfad13 100644 --- a/readme.md +++ b/readme.md @@ -24,6 +24,17 @@ A implementation of workflows of GitHub Actions to support using gitflow on GitH jobs: gitflow: uses: ab180/gitflow/.github/workflows/gitflow.yml@v2 + # inputs: + # MAIN_BRANCH: ... # Default: 'main' + # DEVELOP_BRANCH: ... # Default: 'develop' + # FEATURE_BRANCHES: ... # Default: 'feature refactor fix change update document test chore' + # RELEASE_BRANCHES: ... # Default: 'release hotfix' + # NORELEASE_BRANCHES: ... # Default: 'norelease' + # VERSION_EXPRESSION: ... # Default: '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*' + # VERSION_HEADER: ... # Default: '## ' + # CHANGELOG: ... # Default: 'changelog.md' + # secrets: + # TOKEN: ... # Default: Github Action token ``` 4. Set `Workflow permissions` as checking `Read and write permissions` and `Allow GitHub Actions to create and approve pull requests`. 5. Do not check `Automatically delete head branches`. @@ -83,14 +94,12 @@ changelog.md ``` 1. Create branch from develop branch. -2. Make branch name as `${type}/name`. +2. Make branch name as `${FEATURE_TYPE}/name`. 3. Modify code. 4. Add `## Unreleased` to top of changelog.md when do not contains it. 5. Add description of feature to bottom of `## Unreleased` of changelog.md. 6. Commit and push. -> `type` is `feature` or `refactor` or `fix` or `change` or `update` or `document` or `test`. - ### When finish feature ```mermaid @@ -115,13 +124,11 @@ changelog.md ... ``` -1. Create (`${type}/name` to `develop`) pull request. +1. Create (`${FEATURE_TYPE}/name` to `develop`) pull request. 2. GitHub Actions automatically check changelog.md has `## Unreleased`, if not close pull request. 3. GitHub Actions automatically check changelog.md has modification, if not add recommend comment to pull request. 4. Merge. -5. GitHub Actions automatically delete `${type}/name` branch. - -> `type` is `feature` or `refactor` or `fix` or `change` or `update` or `document` or `test`. +5. GitHub Actions automatically delete `${FEATURE_TYPE}/name` branch. ### When start new release or hotfix @@ -145,7 +152,7 @@ changelog.md ``` 1. Create branch from develop branch. -2. Make branch name as `release/0.0.0` or `hotfix/0.0.0`. +2. Make branch name as `${RELEASE_TYPE}/0.0.0`. 3. Modify code to change version. 4. Modify `## Unreleased` to `## 0.0.0` of changelog.md. @@ -194,7 +201,7 @@ changelog.md 8. GitHub Actions automatically merge `release/0.0.0` or `hotfix/0.0.0` branch to `develop` branch. 9. GitHub Actions automatically delete `release/0.0.0` or `hotfix/0.0.0` branch. -### When finish unrelease +### When finish norelease ```mermaid %%{ init: { 'gitGraph': { 'showCommitLabel': false,'mainBranchName': 'main' } } }%% @@ -203,16 +210,16 @@ changelog.md commit tag: "1.0.0" branch develop commit - branch unrelease/1.1.0 + branch norelease/1.1.0 commit commit checkout main - merge unrelease/1.1.0 tag: "1.1.0" + merge norelease/1.1.0 tag: "1.1.0" checkout develop - merge unrelease/1.1.0 + merge norelease/1.1.0 ``` -1. Create (`unrelease/0.0.0` to `main`) pull request. +1. Create (`{NORELEASE_TYPE}/0.0.0` to `main`) pull request. 2. Merge. -3. GitHub Actions automatically merge `unrelease/0.0.0` branch to `develop` branch. -4. GitHub Actions automatically delete `unrelease/0.0.0` branch. +3. GitHub Actions automatically merge `{NORELEASE_TYPE}/0.0.0` branch to `develop` branch. +4. GitHub Actions automatically delete `{NORELEASE_TYPE}/0.0.0` branch. From 8f6ea1c7bc2d7bde4346ecf7bcfce2e219f16cd1 Mon Sep 17 00:00:00 2001 From: Subeom Choi Date: Fri, 26 Apr 2024 02:13:26 +0900 Subject: [PATCH 2/3] update: use 2.1.0 version --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index bbcb022..b0dff04 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,4 @@ -## Unreleased +## 2.1.0 - feature: add customizable feature. From 4fbdbdbb65264dff19a4dde5572bb3c7c1e9100c Mon Sep 17 00:00:00 2001 From: Subeom Choi Date: Wed, 26 Jun 2024 01:34:55 +0900 Subject: [PATCH 3/3] feature: support fetching github token from github app --- .github/workflows/gitflow.yml | 31 +++++++++++++++++++++++++++++-- changelog.md | 4 ++++ readme.md | 5 ++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gitflow.yml b/.github/workflows/gitflow.yml index 70df2af..ff0c3c7 100644 --- a/.github/workflows/gitflow.yml +++ b/.github/workflows/gitflow.yml @@ -53,9 +53,18 @@ on: default: 'changelog.md' required: false secrets: - TOKEN: + GITHUB_TOKEN: description: 'GitHub token (Default: GitHub Action token)' required: false + GITHUB_APP_ID: + description: 'GitHub app id for fetching GitHub token' + required: false + GITHUB_APP_PRIVATE_KEY: + description: 'GitHub app private key for fetching GitHub token' + required: false + GITHUB_APP_OWNER: + description: 'GitHub app owner for fetching GitHub token' + required: false env: MAIN_BRANCH: ${{ inputs.MAIN_BRANCH || 'main' }} @@ -66,7 +75,10 @@ env: VERSION_EXPRESSION: ${{ inputs.VERSION_EXPRESSION || '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*' }} VERSION_HEADER: ${{ inputs.VERSION_HEADER || '## ' }} CHANGELOG: ${{ inputs.CHANGELOG || 'changelog.md' }} - GITHUB_TOKEN: ${{ secrets.TOKEN || github.token }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN || github.token }} + GITHUB_APP_ID: ${{ secrets.GITHUB_APP_ID }} + GITHUB_APP_PRIVATE_KEY: ${{ secrets.GITHUB_APP_PRIVATE_KEY }} + GITHUB_APP_OWNER: ${{ secrets.GITHUB_APP_OWNER }} SOURCE_BRANCH: ${{ github.event.pull_request.head.ref }} SOURCE_COMMIT: ${{ github.event.pull_request.head.sha }} DESTINATION_BRANCH: ${{ github.event.pull_request.base.ref }} @@ -76,6 +88,21 @@ jobs: gitflow: runs-on: ubuntu-latest steps: + - name: Fetching GitHub Token + id: fetching-github-token + if: ${{ env.GITHUB_APP_ID && env.GITHUB_APP_PRIVATE_KEY && env.GITHUB_APP_OWNER }} + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ env.GITHUB_APP_ID }} + private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }} + owner: ${{ env.GITHUB_APP_OWNER }} + + - name: Using GitHub Token + if: ${{ env.GITHUB_APP_ID && env.GITHUB_APP_PRIVATE_KEY && env.GITHUB_APP_OWNER }} + run: | + echo '::add-mask::${{ steps.fetching-github-token.outputs.token }}' + echo 'GITHUB_TOKEN=${{ steps.fetching-github-token.outputs.token }}' >> $GITHUB_ENV + - name: Check branch id: check-branch run: | diff --git a/changelog.md b/changelog.md index 4c1a5bd..e8b0179 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,7 @@ +## 2.2.0 + +- feature: support fetching github token from github app + ## 2.1.2 - fix: solve issue that DEVELOP_BRANCH input is not used diff --git a/readme.md b/readme.md index 4937ec6..f4749e5 100644 --- a/readme.md +++ b/readme.md @@ -34,7 +34,10 @@ A implementation of workflows of GitHub Actions to support using gitflow on GitH # VERSION_HEADER: ... # Default: '## ' # CHANGELOG: ... # Default: 'changelog.md' # secrets: - # TOKEN: ... # Default: Github Action token + # GITHUB_TOKEN: ... # Default: GitHub Action token + # GITHUB_APP_ID: ... # Default: GitHub App ID for fetching GitHub token + # GITHUB_APP_PRIVATE_KEY: ... # Default: GitHub App ID for fetching GitHub token + # GITHUB_APP_OWNER: ... # Default: GitHub App ID for fetching GitHub token ``` 4. Set `Workflow permissions` as checking `Read and write permissions` and `Allow GitHub Actions to create and approve pull requests`. 5. Do not check `Automatically delete head branches`.