https://github.com/hoangvvo/gitflow-workflow-action
https://github.com/hoangvvo/gitflow-workflow-action
Last synced: 9 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/hoangvvo/gitflow-workflow-action
- Owner: hoangvvo
- License: mit
- Created: 2022-08-27T16:01:28.000Z (over 3 years ago)
- Default Branch: develop
- Last Pushed: 2024-01-27T08:08:46.000Z (almost 2 years ago)
- Last Synced: 2025-03-21T19:01:32.370Z (9 months ago)
- Language: JavaScript
- Size: 948 KB
- Stars: 19
- Watchers: 3
- Forks: 8
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# gitflow-workflow-action
A GitHub actions that automate the [Gitflow workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) where one has a `develop` branch for continuous development and a `main` (production) branch that would automatically deploy to production. In between that, a `release` branch is created from `develop` to perform release preparation tasks before being merged to `main` branch. Occasionally, a `hotfix` branch is created from `main` for hot fixes.

## Usage
Create `.github/workflows/release.yml`:
```yaml
on:
workflow_dispatch:
inputs:
version:
type: string
required: true
description: "Version to release"
pull_request:
types:
- closed
name: Release
jobs:
release_workflow:
runs-on: ubuntu-latest
steps:
- name: gitflow-workflow-action release workflows
uses: hoangvvo/gitflow-workflow-action@
with:
develop_branch: "develop"
main_branch: "main"
merge_back_from_main: false
version: ${{ inputs.version }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
## Inputs
| Name | Description | Default |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
| `develop_branch` | Name of the develop branch | `develop` |
| `main_branch` | Name of the main branch | `main` |
| `merge_back_from_main` | If `"true"`, there will be a merge back from `main` instead of the release branch to `develop` after a release is created. See [this Stackoverflow discussion](https://stackoverflow.com/questions/46604715/gitflow-merging-release-bugfixes-back-to-develop-from-master). | `"false"` |
| `version` | Version to release | |
| `version_increment` | If `version` is not specified, this value will be used to increment the version based on semver. Valid values are `major`, `minor`, `patch`, `premajor`, `preminor`, `prepatch`, `prerelease`. If `version` is specified, this value will be ignored. | |
| `dry_run` | If `"true"`, the action will not create any PRs or releases. It will only print out the steps it would take and some outputs like pull_numbers_in_release. | `"false"` |
| `release_summary` | Specify the release summary to be put in the last section of the release PR | `""` |
Alternatively, the following environment variables can be used: `DEVELOP_BRANCH`, `MAIN_BRANCH`, `MERGE_BACK_FROM_MAIN`, `VERSION`, `DRY_RUN`, `RELEASE_SUMMARY`.
## Outputs
Depending on the workflow types, some outputs might be present:
| Name | Description |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `type` | Type of the release: `release`, `hotfix`, `none` |
| `version` | Version of the release. |
| `pull_number` | Pull request number. (only for `workflow_dispatch`) |
| `pull_numbers_in_release` | Comma separated pull request numbers as shown in the What's changed section of the release. (only for `workflow_dispatch`) |
| `release_branch` | Name of the release branch. (only after merging release PR) |
| `release_url` | URL to the release page. (only after merging release PR) |
| `latest_release_tag_name` | Name of the latest release tag (only for `workflow_dispatch`). |
## Workflows
There are two different workflows covered by this action:
### Create "Deploy to production" PR

This applies when this workflow is triggered from the "Run workflow" window (`workflow_dispatch`).
The process of creating a release start with creating a PR with release note that contains all the new changes in the body. The new branch would be called `release/x.y.z`.
This basically "freezes" the `develop` branch for releases. Other PRs can be merged to `develop` during the `release` branch lifetime without affecting it.
### Workflows for release lifecycle
This detects when the pull request created with the use case above.
This workflow does several things:
- If the PR has a branch that is prefixed with `release` or `hotfix` and merged to `main`, it will create a release, merge back to `develop` branch, and trigger integrations. This is the process in Gitflow.
Note: It does not handle the deployment process. That is for your team to implement separately.
## Integration: Post to Slack
It is often that an anouncement is made to a Slack channel after a release. To do so, specify `SLACK_TOKEN` env and `slack` input.
Alternatively, you can also use the environment variable `SLACK_OPTIONS` instead of `slack` input.
```yaml
jobs:
release_workflow:
steps:
- name: gitflow-workflow-action release workflows
uses: hoangvvo/gitflow-workflow-action@
with:
slack: >
{
"channel": "hoang-test",
"username_mapping": {
"hoangvvo": "U03B3E4UPV3"
}
}
env:
SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}
```
## Example: Prefill release summary
Using the `pull_numbers_in_release` output and dry run mode, you can prefill the PR body with the release summary depending on your PR template.
Let's assume the PR template is:
```md
## What does this PR do?
xxx <-- we want to extract this
## How should this be manually tested?
xxx
## What are the requirements to deploy to production?
xxx
## Any background context you want to provide beyond Shortcut?
xxx
## Screenshots (if appropriate)
xxx
```
```yaml
jobs:
release_workflow:
runs-on: ubuntu-latest
steps:
# This step is only run for `generate_pr_summary` step
# which is only run when the workflow is triggered from the "Run workflow" window
- id: release_workflow_dry_run
name: gitflow-workflow-action release workflows
if: github.event_name == 'workflow_dispatch'
uses: hoangvvo/gitflow-workflow-action@
with:
develop_branch: "develop"
main_branch: "main"
dry_run: true
- id: generate_pr_summary
name: generate pr summary
if: ${{ steps.release_workflow_dry_run.outputs.type == 'release' and steps.release_workflow_dry_run.outputs.pull_numbers_in_release }}
uses: actions/github-script@v7
with:
scripts: |
const pull_numbers_in_release = "${{ steps.release_workflow_dry_run.outputs.pull_numbers_in_release }}";
const mergedPrNumbers = Array.from(new Set(pull_numbers_in_release.split(',').map(Number)));
// Get the PRs and parse the release summary
const mergedPrs = await Promise.all(mergedPrNumbers.map(async (prNumber) => {
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
if (!pr.data.body) {
return;
}
const regex = /\#\# What does this PR do\?([\s\S]*?)\n\#\#/gm;
let match = regex.exec(pr.data.body)?.[1]?.trim();
// try to remove empty lines
match = match?.split('\n').map(s => s.trim()).filter(Boolean).map(
s => s.startsWith('-') || s.startsWith('*') ? s : `* ${s}`
).join('\n');
return `${pr.data.title}\n${match}`;
})).then((prs) => prs.filter(Boolean));
const releaseSummary = mergedPrs.join('\n\n');
return resultSummary;
result-encoding: string
- id: release_workflow
name: gitflow-workflow-action release workflows
uses: hoangvvo/gitflow-workflow-action@
with:
develop_branch: "develop"
main_branch: "main"
version: ${{ inputs.version }}
release_summary: ${{ steps.generate_pr_summary.outputs.result }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
## License
[MIT](LICENSE)