Files
auto-versioning-action/index.js
2025-11-24 20:22:23 +01:00

235 lines
6.1 KiB
JavaScript

/*
Explanation of what this script does:
1. It checks if there is already a version tag in the given repo
--> if so, it checks if the commit history contains hints wether or not to increase the version number in a certain place
--> if not:
It will use the default version tag for creating the first
It then gives back a new version tag and a commit history as outputs to use in later stages
*/
const core = require('@actions/core');
const exec = require('@actions/exec');
const { giteaApi, Api } = require('gitea-js');
const fetch = require('cross-fetch');
/**
* @type {Api}
*/
let api;
async function Run() {
try {
console.log("Running version bumper");
const inputData = await GetInputData();
api = giteaApi('http://gitea.int.boger.local', {
token: inputData.token,
customFetch: fetch,
});
const lastTag = await TryGetLastTag(inputData);
console.log("Last found tag to work with: ", lastTag);
const commitHistory = await GetCommitHistory(inputData, lastTag);
console.log("Commit history: ", commitHistory);
const newTagData = await CreateNewTagData(inputData, lastTag, commitHistory);
console.log("New tag data: ", newTagData);
const patchNotes = await BuildPatchNotes(inputData, commitHistory);
console.log("Patchnotes: ", patchNotes);
// Output the new version
core.setOutput('newTag', newTagData.newTag);
if(patchNotes != null) core.setOutput('patchNotes', patchNotes);
} catch (error) {
console.log(error.message);
core.setFailed(error.message);
}
}
async function GetInputData() {
// Input parameters
const repo_name_comb_name = core.getInput('gitea_repo').split("/");
const res = {
token: core.getInput('gitea_token'),
owner: repo_name_comb_name[0],
repo: repo_name_comb_name[1],
actor: core.getInput('gitea_actor'),
majorKeywords: core.getInput('majorKeywords').split(',').map(x => x.trim()),
minorKeywords: core.getInput('minorKeywords').split(',').map(x => x.trim())
};
return res;
}
async function GetCommitHistory(inputData, lastTag) {
if(lastTag == null || lastTag == '') return null;
const owner = inputData.owner;
const repo_name = inputData.repo;
// Get the commit history from the tag to the latest commit
const commitsResponse = await api.repos.repoCompareDiff(owner, repo_name, `${lastTag}...main`);
const commitHistory = commitsResponse.data.commits.map(commit => commit.commit.message);
const commitHistoryHeads = commitHistory.map(x => x.split('\n')[0].trim());
const commitHistoryHeadsDistinct = [...new Set(commitHistoryHeads)];
return {
commitHistory: commitHistory,
commitHistoryHeadsDistinct: commitHistoryHeadsDistinct
};
}
/**
*
* @returns {Promise<string?>}
*/
async function TryGetLastTag(inputData) {
try {
const owner = inputData.owner;
const repo_name = inputData.repo;
const response = await api.repos.repoListTags(owner, repo_name);
const tags = response.data.map(tag => tag.name);
if(tags.length > 0) {
return tags[0];
}
} catch(error) {
console.log(error.message);
}
return null;
}
async function CreateNewTagData(inputData, lastTag, commitHistory) {
//no first tag existing
if(lastTag == null || lastTag == '') {
var defo = core.getInput('default_base_version_tag');
return {
newTag: defo,
lastTag: lastTag,
};
}
// Check if commits contain any major or minor keywords
let newVersion = [];
const regex = /.*(\d+)\.(\d+)\.(\d+).*/;
const matches = regex.exec(lastTag);
if (matches) {
const [, majorVersion, minorVersion, bugfixVersion] = matches;
newVersion = [majorVersion, minorVersion, bugfixVersion];
console.log("Tag match found", newVersion);
} else {
console.error("No tag match found.");
}
let majorChanged = false, minorChanged = false;
// check for minor or major changes if a commit history is avail
if(commitHistory != null) {
console.log("Checking commit history for keywords..");
for (const commit of commitHistory.commitHistory) {
for (const keyword of inputData.majorKeywords) {
if (commit.toLowerCase().includes(keyword.toLowerCase())) {
newVersion[0] = (parseInt(newVersion[0]) + 1).toString();
newVersion[1] = '0';
newVersion[2] = '0';
majorChanged = true;
console.log("Found major keyword in: ", commit);
break;
}
}
if(majorChanged || minorChanged) break;
for (const keyword of inputData.minorKeywords) {
if (commit.toLowerCase().includes(keyword.toLowerCase())) {
newVersion[1] = (parseInt(newVersion[1]) + 1).toString();
newVersion[2] = '0';
minorChanged = true;
console.log("Found minor keyword in: ", commit);
break;
}
}
if(majorChanged || minorChanged) break;
}
}
//no major minor changed, increase bugfix
if(!majorChanged && !minorChanged) {
newVersion[2] = (parseInt(newVersion[2]) + 1).toString();
}
return {
newTag: newVersion.join('.'),
lastTag: lastTag,
};
}
async function BuildPatchNotes(inputData, commitHistory) {
if(commitHistory == null) return null;
// Build simple patchnotes
const commitListString = commitHistory.commitHistoryHeadsDistinct.join('\n- ');
let body = `Released by: @${inputData.actor}`;
if(commitHistory.commitHistoryHeadsDistinct.length > 0) {
body += `\nCommits: ${commitHistory.commitHistoryHeadsDistinct.length}\n\n- ${commitListString}`;
}
return body;
}
async function CreateReleaseAndTag(forTag) {
}
// Run the action
Run();