Skip to content

feature: add customizable feature #6

feature: add customizable feature

feature: add customizable feature #6

Workflow file for this run

name: gitflow
on:
pull_request:
types:
- opened
- synchronize
- reopened
- closed
branches:
- 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:
GITHUB_TOKEN: ${{ secrets.TOKEN || github.token }}
SOURCE_BRANCH: ${{ github.event.pull_request.head.ref }}
SOURCE_COMMIT: ${{ github.event.pull_request.head.sha }}
DESTINATION_BRANCH: ${{ github.event.pull_request.base.ref }}
DESTINATION_COMMIT: ${{ github.event.pull_request.base.sha }}
jobs:
gitflow:
runs-on: ubuntu-latest
steps:
- name: Check branch
id: check-branch
run: |
if [[ $(
if [[ '${{env.DESTINATION_BRANCH}}' != '${{ inputs.DEVELOP_BRANCH }}' ]]; then
echo 'false'
fi
for FEATURE_BRANCH in $(echo '${{ inputs.FEATURE_BRANCHES }}'); do
if [[ '${{ env.SOURCE_BRANCH }}' =~ ^"$FEATURE_BRANCH"/.*$ ]]; then
echo 'true'
fi
done
) == true ]]; then
echo 'type=feature' >> $GITHUB_OUTPUT
elif [[ $(
if [[ '${{env.DESTINATION_BRANCH}}' != '${{ inputs.MAIN_BRANCH }}' ]]; then
echo 'false'
fi
for RELEASE_BRANCH in $(echo '${{ inputs.RELEASE_BRANCHES }}'); do
if [[ '${{ env.SOURCE_BRANCH }}' =~ ^"$RELEASE_BRANCH"/.*$ ]]; then
echo 'true'
fi
done
) == true ]]; then
echo 'type=release' >> $GITHUB_OUTPUT
elif [[ $(
if [[ '${{env.DESTINATION_BRANCH}}' != '${{ inputs.MAIN_BRANCH }}' ]]; then
echo 'false'
fi
for NORELEASE_BRANCH in $(echo '${{ inputs.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}}' != '${{ inputs.DEVELOP_BRANCH }}' ]]; then
echo 'false'
fi
for RELEASE_BRANCH in $(echo '${{ inputs.RELEASE_BRANCHES }}'); do
if [[ '${{ env.SOURCE_BRANCH }}' =~ ^"$RELEASE_BRANCH"/.*$ ]]; then
echo 'true'
fi
done
for NORELEASE_BRANCH in $(echo '${{ inputs.NORELEASE_BRANCHES }}'); do
if [[ '${{ env.SOURCE_BRANCH }}' =~ ^"$NORELEASE_BRANCH"/.*$ ]]; then
echo 'true'
fi
done
) == true ]]; then
echo 'type=update' >> $GITHUB_OUTPUT
else
exit 1
fi
- name: If fail on check branch
if: failure() && steps.check-branch.outcome == 'failure'
uses: actions/github-script@v6
with:
script: |
const message = [
'Invalid pull request: ',
'only ({RELEASE_TYPE}/ => ${{ inputs.MAIN_BRANCH }}) ',
'or ({NORELEASE_TYPE}/ => ${{ inputs.MAIN_BRANCH }}) ',
'or ({FEATURE_TYPE}/ => ${{ inputs.DEVELOP_BRANCH }}) is allowed',
].join('')
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: message,
})
github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
state: 'closed',
})
github-token: ${{ env.GITHUB_TOKEN }}
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ env.GITHUB_TOKEN }}
- name: Checkout commit
run: |
git fetch origin ${{ env.SOURCE_COMMIT }} || :
git fetch origin ${{ env.DESTINATION_COMMIT }} || :
- name: Check feature branch
id: check-feature-branch
if: |
github.event.pull_request.merged != true
&& steps.check-branch.outcome == 'success'
&& steps.check-branch.outputs.type == 'feature'
run: |
cat ${{ inputs.CHANGELOG }} \
| grep '^${{ inputs.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' \
|| (echo 'warning=changelog-not-modified' >> $GITHUB_OUTPUT; exit 0)
- name: If fail on check feature branch
if: failure() && steps.check-feature-branch.outputs.failure != null
uses: actions/github-script@v6
with:
script: |
const message = (() => {
if ('${{ steps.check-feature-branch.outputs.failure }}' === 'changelog-not-contains-unreleased') {
return [
`Invalid pull request: `,
`'${{ inputs.VERSION_HEADER }}Unreleased' `,
`should be existed on ${{ inputs.CHANGELOG }}.`,
].join('')
}
})()
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: message,
})
github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
state: 'closed',
})
github-token: ${{ env.GITHUB_TOKEN }}
- name: If warn on check feature branch
if: always() && steps.check-feature-branch.outputs.warning != null
uses: actions/github-script@v6
with:
script: |
const message = (() => {
if ('${{ steps.check-feature-branch.outputs.warning }}' === 'changelog-not-modified') {
return `I recommend that you should modify ${{ inputs.CHANGELOG }}.`
}
})()
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: message,
})
github-token: ${{ env.GITHUB_TOKEN }}
- name: Check release branch
id: check-release-branch
if: |
github.event.pull_request.merged != true
&& steps.check-branch.outcome == 'success'
&& steps.check-branch.outputs.type == 'release'
run: |
VERSION=$(
echo '${{ env.SOURCE_BRANCH }}' \
| grep '${{ inputs.VERSION_EXPRESSION }}' --only-matching
) \
&& (echo "version=$VERSION" >> $GITHUB_OUTPUT) \
|| (echo 'failure=version-not-found' >> $GITHUB_OUTPUT; exit 1)
cat ${{ inputs.CHANGELOG }} \
| grep '^${{ inputs.VERSION_HEADER }}Unreleased$' \
&& (echo 'failure=changelog-contains-unreleased' >> $GITHUB_OUTPUT; exit 1) \
|| :
cat ${{ inputs.CHANGELOG }} \
| grep "^${{ inputs.VERSION_HEADER }}$VERSION$" \
|| (echo 'failure=changelog-not-contains-version' >> $GITHUB_OUTPUT; exit 1)
CHANGELOG=$(
cat ${{ inputs.CHANGELOG }} \
| perl -0pe "s/(.*\n)*${{ inputs.VERSION_HEADER }}$VERSION\n//g" \
| perl -0pe 's/(\n?)${{ inputs.VERSION_HEADER }}.*\n(.*\n)*/\1/g' \
| perl -0pe 's/^\n*//g' \
| perl -0pe 's/\n*$//g'
) \
&& ! [[ -z $CHANGELOG ]] \
|| (echo 'failure=changelog-is-empty' >> $GITHUB_OUTPUT; exit 1)
- name: If fail on check release branch
if: failure() && steps.check-release-branch.outputs.failure != null
uses: actions/github-script@v6
with:
script: |
const message = (() => {
if ('${{ steps.check-release-branch.outputs.failure }}' === 'version-not-found') {
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: `,
`'${{ inputs.VERSION_HEADER }}Unreleased' `,
`should not be existed on ${{ inputs.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: `,
`'${{ inputs.VERSION_HEADER }}${version}' `,
`should not be existed on ${{ inputs.CHANGELOG }}.`,
].join('')
}
else if ('${{ steps.check-release-branch.outputs.failure }}' === 'changelog-is-empty') {
return `Invalid pull request: changelog is empty.`
}
})()
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: message,
})
github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
state: 'closed',
})
github-token: ${{ env.GITHUB_TOKEN }}
- name: Finish feature branch
id: finish-feature-branch
if: |
github.event.pull_request.merged == true
&& steps.check-branch.outcome == 'success'
&& steps.check-branch.outputs.type == 'feature'
run: |
git push origin --delete ${{ env.SOURCE_BRANCH }} \
|| :
- name: Finish release branch
id: finish-release-branch
if: |
github.event.pull_request.merged == true
&& steps.check-branch.outcome == 'success'
&& steps.check-branch.outputs.type == 'release'
run: |
VERSION=$(
echo '${{ env.SOURCE_BRANCH }}' \
| grep '${{ inputs.VERSION_EXPRESSION }}' --only-matching
)
CHANGELOG=$(
cat ${{ inputs.CHANGELOG }} \
| perl -0pe "s/(.*\n)*${{ inputs.VERSION_HEADER }}$VERSION\n//g" \
| perl -0pe 's/(\n?)${{ inputs.VERSION_HEADER }}.*\n(.*\n)*/\1/g' \
| perl -0pe 's/^\n*//g' \
| perl -0pe 's/\n*$//g'
)
gh release create $VERSION \
--generate-notes \
--notes '## Changelog'$'\n'"$CHANGELOG"$'\n' \
--latest
git checkout -b '${{ env.SOURCE_BRANCH }}' '${{ env.SOURCE_COMMIT }}' \
&& git push -u origin '${{ env.SOURCE_BRANCH }}' \
|| :
PULL_REQUEST_NUMBER=$(
gh pr create \
--head '${{ env.SOURCE_BRANCH }}' \
--base 'develop' \
--title "update: ${{ env.SOURCE_BRANCH }} to develop" \
--body "update: ${{ env.SOURCE_BRANCH }} to develop" \
| grep '\/pull\/[0-9][0-9]*' --only-matching \
| grep '[0-9][0-9]*' --only-matching
)
gh pr merge $PULL_REQUEST_NUMBER \
--subject "update: ${{ env.SOURCE_BRANCH }} to develop" \
--admin \
--merge \
&& git push origin --delete ${{ env.SOURCE_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 == 'norelease'
run: |
git checkout -b '${{ env.SOURCE_BRANCH }}' '${{ env.SOURCE_COMMIT }}' \
&& git push -u origin '${{ env.SOURCE_BRANCH }}' \
|| :
PULL_REQUEST_NUMBER=$(
gh pr create \
--head '${{ env.SOURCE_BRANCH }}' \
--base 'develop' \
--title "update: ${{ env.SOURCE_BRANCH }} to develop" \
--body "update: ${{ env.SOURCE_BRANCH }} to develop" \
| grep '\/pull\/[0-9][0-9]*' --only-matching \
| grep '[0-9][0-9]*' --only-matching
)
gh pr merge $PULL_REQUEST_NUMBER \
--subject "update: ${{ env.SOURCE_BRANCH }} to develop" \
--admin \
--merge \
&& git push origin --delete ${{ env.SOURCE_BRANCH }} \
|| :