Skip to content

Commit

Permalink
feat: generate changelog file
Browse files Browse the repository at this point in the history
  • Loading branch information
ReenigneArcher committed Oct 29, 2023
1 parent 361a8a8 commit 63ef4fa
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 11 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,19 @@ jobs:
id: vars
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
changelog_branch=pr-changelogs
discussion_category=tests
publish_pre_release=true
release_tag=pr-${{ github.event.pull_request.number }}-${{ github.run_id }}
else
changelog_branch=changelog
discussion_category=announcements
publish_pre_release=${{ steps.setup-release.outputs.publish_pre_release }}
release_tag=${{ steps.setup-release.outputs.release_tag }}
fi
# set outputs
echo "changelog_branch=$changelog_branch" >> $GITHUB_OUTPUT
echo "discussion_category=$discussion_category" >> $GITHUB_OUTPUT
echo "publish_stable_release=$publish_stable_release" >> $GITHUB_OUTPUT
echo "release_tag=$release_tag" >> $GITHUB_OUTPUT
Expand All @@ -57,13 +60,18 @@ jobs:
allowUpdates: false
artifacts: ''
body: ''
changelogBranch: ${{ steps.vars.outputs.changelog_branch }}
discussionCategory: ${{ steps.vars.outputs.discussion_category }}
generateReleaseNotes: true
name: ${{ steps.vars.outputs.release_tag }}
prerelease: ${{ steps.vars.outputs.publish_pre_release == 'true' }}
tag: ${{ steps.vars.outputs.release_tag }}
token: ${{ secrets.GH_BOT_TOKEN }}

- name: Print changelog
run: |
echo "${{ steps.action.outputs.changelog }}"
- name: Sleep
if: ${{ always() && github.event_name == 'pull_request' }}
run: sleep 60
Expand Down
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,25 @@ steps:
## Inputs
| Name | Description | Default | Required |
|----------------------|--------------------------------------------------------------------------------------|-----------------|----------|
| allowUpdates | An optional flag which indicates if we should update a release if it already exists. | `true` | `false` |
| artifacts | The artifacts to upload. | `*artifacts/*` | `false` |
| body | The body of the release. | | `false` |
| discussionCategory | The category for the discussion. | `announcements` | `false` |
| generateReleaseNotes | Indicates if release notes should be automatically generated. | `false` | `false` |
| name | The version to create. | | `true` |
| prerelease | Whether the release is a prerelease. | `false` | `false` |
| tag | The tag to create. | | `true` |
| token | GitHub Token. | | `true` |
| Name | Description | Default | Required |
|----------------------|---------------------------------------------------------------------------------------------------|-----------------|----------|
| allowUpdates | An optional flag which indicates if we should update a release if it already exists. | `true` | `false` |
| artifacts | The artifacts to upload. | `*artifacts/*` | `false` |
| body | The body of the release. | | `false` |
| changelog | Whether to create a changelog file. The changelog will be generated from the GitHub releases API. | `true` | `false` |
| changelogBranch | The branch to store the changelog in. | `changelog` | `false` |
| discussionCategory | The category for the discussion. | `announcements` | `false` |
| generateReleaseNotes | Indicates if release notes should be automatically generated. | `false` | `false` |
| name | The version to create. | | `true` |
| prerelease | Whether the release is a prerelease. | `false` | `false` |
| tag | The tag to create. | | `true` |
| token | GitHub Token. | | `true` |

## Outputs

| Name | Description |
|-----------|------------------------------------------|
| changelog | The contents of the generated changelog. |

## See Also

Expand Down
130 changes: 130 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ inputs:
description: 'The body of the release.'
required: false
default: ''
changelog:
description: 'Whether to create a changelog file.'
required: false
default: 'true'
changelogBranch:
description: 'The branch to store the changelog in.'
required: false
default: 'changelog'
discussionCategory:
description: 'The category of the discussion.'
required: false
Expand Down Expand Up @@ -57,3 +65,125 @@ runs:
prerelease: ${{ inputs.prerelease }}
tag: ${{ inputs.tag }}
token: ${{ inputs.token }}

- name: Emtpy sha
id: empty_sha
if: >-
inputs.changelog == 'true' &&
(github.repository == 'LizardByte/create-release-action' ||
(github.event_name == 'push' && github.ref == 'refs/heads/master'))
run: |
# get empty sha from git
# https://stackoverflow.com/a/9766506
# empty sha is derived from `git hash-object -t tree /dev/null`
echo "emtpy_sha=$(git hash-object -t tree /dev/null)" >> $GITHUB_ENV
shell: bash

- name: Create Changelog
if: >-
inputs.changelog == 'true' &&
(github.repository == 'LizardByte/create-release-action' ||
(github.event_name == 'push' && github.ref == 'refs/heads/master'))
uses: actions/github-script@v6
with:
github-token: ${{ inputs.token }}
script: |
// get inputs
const changelogBranch = core.getInput('changelogBranch')
// -- general logic of this script --
// get changelog content from github releases api, use body of each release
// store in changelog branch
// if changelog branch doesn't exist, create it with no parents, history, etc.
// only the changelog should be in this branch, none of the code on the current branch
// check if changelog branch exists
const changelogBranchExists = await github.repos.getBranch({
owner: context.repo.owner,
repo: context.repo.repo,
branch: changelogBranch
}).then(() => true).catch(() => false)
// create empty/orphaned changelog branch if it doesn't exist
if (!changelogBranchExists) {
emtpy_sha = process.env.emtpy_sha
await github.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `refs/heads/${changelogBranch}`,
sha: emtpy_sha
})
}
// only checkout changelog branch
await github.git.checkout({
owner: context.repo.owner,
repo: context.repo.repo,
ref: changelogBranch
})
// get all releases and sort by date created, page if required
let releases = []
let page = 1
let per_page = 100
let total = 0
do {
const response = await github.repos.listReleases({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: per_page,
page: page
})
releases = releases.concat(response.data)
total = response.data.length
page++
} while (total == per_page)
// sort releases by date created
releases.sort((a, b) => {
return new Date(a.created_at) - new Date(b.created_at)
})
// create a CHANGELOG.md and initialize it
changelog = '# Changelog\n\n`
changelog += 'All notable changes to this project will be documented in this file.\n\n'
changelog += 'The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),\n'
changelog += 'and this project adheres to [Calendar Versioning](https://calver.org/).\n\n'
// loop through each release
for (const release of releases) {
// get release body
const body = release.body
// get release tag
const tag = release.tag_name
// get release date
const date = release.created_at
// get release name
const name = release.name
// add release to changelog
changelog += `## [${tag}] - ${date}\n\n`
changelog += `${body}\n\n`
}
// add urls to end of changelog
for (const release of releases.reverse()) {
// get release url
const url = release.html_url
// add release url to changelog
changelog += `[${url}]: ${url}\n`
}
// write changelog to CHANGELOG.md
await github.repos.createOrUpdateFileContents({
owner: context.repo.owner,
repo: context.repo.repo,
path: 'CHANGELOG.md',
message: 'chore: update CHANGELOG.md',
content: Buffer.from(changelog).toString('base64'),
branch: changelogBranch
})
// set github output
core.setOutput('changelog', changelog)

0 comments on commit 63ef4fa

Please sign in to comment.