Skip to content

Event that fires auto-changelog #29

Event that fires auto-changelog

Event that fires auto-changelog #29

name: "Auto Changelog"
on:
pull_request:
types: [labeled]
jobs:
auto-changelog:
env:
PR_LABELED: ${{ github.event.pull_request.labels }}
PR_TITLE: ${{ github.event.pull_request.title }}
if: ${{ contains(github.event.pull_request.body, '+changelog') || contains(github.event.pull_request.body, '-changelog') }}
runs-on: ubuntu-latest
steps:
- run: echo '${{ github.event.pull_request.labels }}'
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
clean: false
fetch-depth: 0
filter: tree:0
- run: |
git branch --track ${{ github.base_ref }} origin/${{ github.base_ref }}
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_SIGNING_PASSPHRASE }}
git_user_signingkey: true
git_commit_gpgsign: true
- name: Reset Changelog
continue-on-error: true
run: |
rm CHANGELOG.md
git checkout ${{ github.base_ref }} -- CHANGELOG.md
- name: CHANGELOG Setup
if: ${{ contains(github.event.pull_request.body, '+changelog') }}
uses: actions/github-script@v7
env:
HEAD_REF: ${{ github.head_ref }}
ISSUE_TITLE: ${{ env.PR_TITLE }}
with:
script: |
const fs = require('fs');
const filePath = 'CHANGELOG.md';
const headRef = process.env.HEAD_REF;
Array.prototype.insert = function ( index, ...items ) {
this.splice( index, 0, ...items );
};
class MarkdownHead {
constructor(level = 0, parent = null) {
this.level = level;
this.children = [];
if (parent != null && parent.children != null)
parent.children.push(this);
}
findOrCreateChildHead(firstLineContains, template) {
for (var idx = 0; idx < this.children.length; idx++) {
var cur = this.children[idx];
if (typeof(cur) == typeof('') || cur.children == null) continue;
if (cur.children.length > 0 && cur.children[0].toLowerCase().includes(firstLineContains.toLowerCase())) {
return cur;
}
}
var newHead = new MarkdownHead(this.level + 1, this);
if (template != null)
newHead.children = template.split('\n');
else
newHead.children = [ '#'.repeat(newHead.level) + ' ' + firstLineContains ];
return newHead;
}
cleanup() {
while (this.children.length > 0 && typeof(this.children[this.children.length - 1]) == typeof('') && this.children[this.children.length - 1].replace(' ', '') == '')
this.children.pop();
while (this.children.length > 0 && typeof(this.children[0]) == typeof('') && this.children[0].replace(' ', '') == '')
this.children.remove(0);
}
parse(markdown) {
var inChild = false;
const markdownSplit = markdown.split('\n');
const headStack = [ this ];
for (var idx = 0; idx < markdownSplit.length; idx++) {
const currentLine = markdownSplit[idx];
const match = currentLine.match(/^(#+).*$/)
const matchLevel = match != null ? match[1].length : -1;
var newHead;
// Handle all head changes
if (match && matchLevel > headStack[headStack.length - 1].level) {
newHead = new MarkdownHead(matchLevel, headStack[headStack.length - 1]);
headStack.push(newHead);
} else if (match && matchLevel == headStack[headStack.length - 1].level) {
headStack.pop().cleanup();
newHead = new MarkdownHead(matchLevel, headStack[headStack.length - 1]);
headStack.push(newHead);
} else if (match && matchLevel < headStack[headStack.length - 1].level) {
while (matchLevel <= headStack[headStack.length - 1].level) {
headStack.pop().cleanup();
}
newHead = new MarkdownHead(matchLevel, headStack[headStack.length - 1]);
headStack.push(newHead);
}
const currentHead = headStack[headStack.length - 1];
currentHead.children.push(currentLine);
}
this.cleanup();
}
toString() {
var curString = "";
for (var idx = 0; idx < this.children.length; idx++) {
const curElem = this.children[idx];
if (typeof(curElem) == typeof(""))
curString += `${curElem}\n`;
else {
if (curElem.children.length <= 1)
continue; // Skip empty sections
if (curElem.children.length > 1 && curElem.children[1] != "")
curElem.children.insert(1, "");
if (curElem.children.length > 0 && curElem.children[0] != "" &&
curString.length > 0 && !curString.endsWith('\n\n'))
curElem.children.insert(0, "");
curString += curElem.toString();
}
}
return curString;
}
}
const DefaultChangelog = `# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).`;
// Check if the file exists and read its content if it does
let fileContent = '';
if (fs.existsSync(filePath)) {
fileContent = fs.readFileSync(filePath, 'utf8');
}
const masterHead = new MarkdownHead();
masterHead.parse(fileContent);
(() => { //
masterHead.changelog = masterHead.findOrCreateChildHead("Changelog", DefaultChangelog);
masterHead.changelog.unreleased = masterHead.changelog.findOrCreateChildHead("[Unreleased]");
masterHead.changelog.unreleased.added =
masterHead.changelog.unreleased.findOrCreateChildHead("Added");
masterHead.changelog.unreleased.changed =
masterHead.changelog.unreleased.findOrCreateChildHead("Changed");
masterHead.changelog.unreleased.deprecated =
masterHead.changelog.unreleased.findOrCreateChildHead("Deprecated");
masterHead.changelog.unreleased.removed =
masterHead.changelog.unreleased.findOrCreateChildHead("Removed");
masterHead.changelog.unreleased.fixed =
masterHead.changelog.unreleased.findOrCreateChildHead("Fixed");
masterHead.changelog.unreleased.secured =
masterHead.changelog.unreleased.findOrCreateChildHead("Secured");
})();
console.log(headRef);
var category = headRef.split('/')[0];
var potentialHead = masterHead.changelog.unreleased[category];
console.log(potentialHead);
if (potentialHead != null) {
potentialHead.children.push('- ' + process.env.ISSUE_TITLE);
}
fs.writeFileSync(filePath, masterHead.toString());
console.log("-=-=-=-=-\nWhat we have exported...");
console.log(masterHead.toString());
- run: |
git add .
git commit -am "Updated CHANGELOG.md"
- name: PR Check
id: pr-check
uses: actions/github-script@v7
with:
script: |
const execSync = require('child_process').execSync;
const branchStatus = execSync('git status -sb').toString();
const result = branchStatus.match(/^##\s*([\w\d-_/\\]+)\.\.\.([\w\d-_/\\]+)/)
if (!result)
throw new Exception("Weird");
const currentBranch = result[1];
const trackingBranch = result[2];
const diff = execSync(`git diff ${currentBranch} ${trackingBranch}`).toString();
core.setOutput('push-needed', diff != "" ? 'true' : 'false');
console.log(currentBranch);
console.log(trackingBranch);
console.log(diff);
- name: Push Changes
if: steps.pr-check.outputs.push-needed == 'true'
run: |
git push