Skip to content

Commit

Permalink
feat: initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
ReenigneArcher committed May 19, 2024
1 parent 68c4d05 commit de19061
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 2 deletions.
67 changes: 67 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
name: CI

on:
pull_request:
branches: [master]
types: [opened, synchronize, reopened]
push:
branches: [master]
workflow_dispatch:

concurrency:
group: "${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true

jobs:
action:
environment:
${{ github.event_name == 'pull_request' &&
github.event.pull_request.head.repo.full_name != github.repository &&
'external' || 'internal' }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Release
id: setup-release
uses: LizardByte/setup-release-action@fix!-updates # todo: change to latest
with:
github_token: ${{ secrets.GITHUB_TOKEN }} # can use GITHUB_TOKEN for read-only access

- name: Set action variables
id: vars
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
changelog_branch=pr-changelogs
changelog_file=PR-${{ github.event.pull_request.number }}-CHANGELOG.md
else
changelog_branch=changelog
changelog_file=CHANGELOG.md
fi
# set outputs
echo "changelog_branch=$changelog_branch" >> $GITHUB_OUTPUT
echo "changelog_file=$changelog_file" >> $GITHUB_OUTPUT
- name: Run Action
id: action
uses: ./
with:
changelogBranch: ${{ steps.vars.outputs.changelog_branch }}
changelogFile: ${{ steps.vars.outputs.changelog_file }}
token: ${{ secrets.GH_BOT_TOKEN }}

- name: Create/Update GitHub Release
if: ${{ steps.setup-release.outputs.publish_release == 'true' }}
uses: LizardByte/create-release-action@fix!-updates # todo: change to latest
with:
allowUpdates: false
artifacts: ""
discussionCategory: announcements
generateReleaseNotes: true
name: ${{ steps.setup-release.outputs.release_tag }}
prerelease: true
tag: ${{ steps.setup-release.outputs.release_tag }}
token: ${{ secrets.GH_BOT_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# ignore jetbrains files
.idea/
37 changes: 35 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
# template-base
Base repository template for LizardByte.
# update-changelog-action
[![GitHub Workflow Status (CI)](https://img.shields.io/github/actions/workflow/status/lizardbyte/update-changelog-action/ci.yml.svg?branch=master&label=CI%20build&logo=github&style=for-the-badge)](https://github.com/LizardByte/update-changelog-action/actions/workflows/ci.yml?query=branch%3Amaster)

A reusable action to update a changelog, based on the contents of the GitHub releases.

## Basic Usage

See [action.yml](action.yml)

```yaml
steps:
- name: Update Changelog
uses: LizardByte/update-changelog-action@master
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
## Inputs
| Name | Description | Default | Required |
|------------------------|----------------------------------------|-----------------|----------|
| changelogBranch | The branch to store the changelog in. | `changelog` | `false` |
| changelogFile | The file to store the changelog in. | `CHANGELOG.md` | `false` |
| token | GitHub Token. | | `true` |

## Outputs

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

## See Also

This action is meant to be used in conjunction with
[LizardByte/setup-release-action](https://github.com/LizardByte/setup-release-action).
163 changes: 163 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
---
name: "Update changelog"
description: "A reusable action to automatically update a changelog based on GitHub releases."
author: "LizardByte"
inputs:
changelogBranch:
description: 'The branch to store the changelog in.'
required: false
default: 'changelog'
changelogFile:
description: 'The file to store the changelog in.'
required: false
default: 'CHANGELOG.md'
token:
description: 'Github Token.'
required: true

runs:
using: "composite"
steps:
- name: Create Changelog
env:
changelog_branch: ${{ inputs.changelogBranch }}
changelog_file: ${{ inputs.changelogFile }}
uses: actions/github-script@v7
with:
github-token: ${{ inputs.token }}
script: |
// get inputs
const changelogBranch = process.env.changelog_branch
const changelogFile = process.env.changelog_file
// 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.rest.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
let changelog = '<!-- # Changelog -->\n\n' // commenting out due to how sphinx renders this
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'
changelog += 'This changelog was automatically generated by the\n'
changelog += '[create-release-action](https://github.com/LizardByte/create-release-action).\n\n'
// loop through each release
releases = releases.reverse()
for (const release of releases) {
// add release to changelog
let created_date = new Date(release.created_at)
let year = created_date.getFullYear()
let month = (created_date.getMonth() + 1).toString().padStart(2, '0')
let day = created_date.getDate().toString().padStart(2, '0')
let date = `${year}-${month}-${day}`
// replace lines such as `## Any Text\n` with `**Any Text**\n`
// let release_body = release.body.replace(/## (.*)\n/g, '**$1**\n')
// replace lines such as `## Any Text\n` with `### Any Text\n`
let release_body = release.body.replace(/## (.*)\n/g, '### $1\n')
changelog += `## [${release.tag_name}] - ${date}\n\n${release_body}\n\n`
}
// add urls to end of changelog
for (const release of releases) {
// add release url to changelog
changelog += `[${release.tag_name}]: ${release.html_url}\n`
}
try {
// Directly create a tree with CHANGELOG.md in it
const blob = await github.rest.git.createBlob({
owner: context.repo.owner,
repo: context.repo.repo,
content: changelog,
encoding: 'utf-8'
})
const tree = await github.rest.git.createTree({
owner: context.repo.owner,
repo: context.repo.repo,
tree: [{
path: changelogFile,
mode: '100644',
type: 'blob',
sha: blob.data.sha
}]
})
const commit = await github.rest.git.createCommit({
owner: context.repo.owner,
repo: context.repo.repo,
message: `chore: create ${changelogFile}`,
tree: tree.data.sha,
parents: [] // Empty parents array for a truly orphaned commit
})
await github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `refs/heads/${changelogBranch}`,
sha: commit.data.sha
})
} catch (e) {
if (e.status === 422 && e.message.includes("Reference already exists")) {
let sha = null; // Initialize the sha to null by default
// Branch already exists, try to fetch the SHA of the specified changelogFile
try {
const fileData = await github.rest.repos.getContent({
owner: context.repo.owner,
repo: context.repo.repo,
path: changelogFile,
ref: changelogBranch
});
sha = fileData.data.sha; // Update the sha if the file exists
} catch (getFileError) {
if (getFileError.status !== 404) {
// If the error is not a 'not found' error, set the action as failed
core.setFailed(`Failed to fetch the file: ${getFileError.message}`);
return;
}
// If the error is 'not found' error, we'll continue with sha as null, resulting in file creation
}
try {
// Create or Update the file using the same call
await github.rest.repos.createOrUpdateFileContents({
owner: context.repo.owner,
repo: context.repo.repo,
path: changelogFile,
message: sha ? `chore: update ${changelogFile}` : `chore: create ${changelogFile}`,
content: Buffer.from(changelog).toString('base64'),
sha: sha, // if sha is null, it'll create a new file
branch: changelogBranch
});
} catch (updateError) {
core.setFailed(`Failed to create or update the file: ${updateError.message}`);
}
} else {
// Some other error occurred
core.setFailed(`Action failed with error: ${e.message}`);
}
}
// Set GitHub action output
core.setOutput('changelog', changelog);

0 comments on commit de19061

Please sign in to comment.