build: fixed tl versioning + changelog generation
This commit is contained in:
parent
f525c12f83
commit
ec1154fdef
6 changed files with 122 additions and 23 deletions
8
.github/workflows/release.yaml
vendored
8
.github/workflows/release.yaml
vendored
|
@ -48,6 +48,9 @@ jobs:
|
||||||
- name: Find packages to publish
|
- name: Find packages to publish
|
||||||
id: find
|
id: find
|
||||||
run: node scripts/find-updated-packages.js ${{ inputs.kind }} ${{ inputs.packages }}
|
run: node scripts/find-updated-packages.js ${{ inputs.kind }} ${{ inputs.packages }}
|
||||||
|
- name: Generate changelog
|
||||||
|
id: changelog
|
||||||
|
run: node scripts/generate-changelog.js ${{ steps.find.outputs.modified }}
|
||||||
- name: Bump versions
|
- name: Bump versions
|
||||||
id: bump
|
id: bump
|
||||||
run: node scripts/bump-version.js ${{ inputs.kind }} ${{ steps.find.outputs.modified }}
|
run: node scripts/bump-version.js ${{ inputs.kind }} ${{ steps.find.outputs.modified }}
|
||||||
|
@ -55,7 +58,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
git commit -am "v${{ steps.bump.outputs.version }}"
|
git commit -am "v${{ steps.bump.outputs.version }}"
|
||||||
git push
|
git push
|
||||||
- name: Build pacakges and publish to NPM
|
- name: Build packages and publish to NPM
|
||||||
id: build
|
id: build
|
||||||
env:
|
env:
|
||||||
GH_RELEASE: 1
|
GH_RELEASE: 1
|
||||||
|
@ -66,6 +69,7 @@ jobs:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
tag: v${{ steps.bump.outputs.version }}
|
tag: v${{ steps.bump.outputs.version }}
|
||||||
name: v${{ steps.bump.outputs.version }}
|
name: v${{ steps.bump.outputs.version }}
|
||||||
artifacts: ${{ steps.build.outputs.tarballs }}}
|
artifacts: ${{ steps.build.outputs.tarballs }}
|
||||||
|
body: ${{ steps.changelog.outputs.changelog }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@mtcute/tl",
|
"name": "@mtcute/tl",
|
||||||
"version": "0.1.0",
|
"version": "166.0.0",
|
||||||
"description": "TL schema used for mtcute",
|
"description": "TL schema used for mtcute",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"author": "Alina Sireneva <alina@tei.su>",
|
"author": "Alina Sireneva <alina@tei.su>",
|
||||||
|
|
|
@ -29,6 +29,7 @@ function bumpVersions(packages, kind) {
|
||||||
console.log('[i] Bumping versions to %s', nextVersion)
|
console.log('[i] Bumping versions to %s', nextVersion)
|
||||||
|
|
||||||
for (const pkg of packages) {
|
for (const pkg of packages) {
|
||||||
|
if (pkg === 'tl') continue // own versioning
|
||||||
const pkgJson = pkgJsons.find((it) => it.name === `@mtcute/${pkg}`)
|
const pkgJson = pkgJsons.find((it) => it.name === `@mtcute/${pkg}`)
|
||||||
|
|
||||||
if (!pkgJson) {
|
if (!pkgJson) {
|
||||||
|
|
|
@ -2,25 +2,7 @@ const cp = require('child_process')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const { listPackages } = require('./publish')
|
const { listPackages } = require('./publish')
|
||||||
|
const { getLatestTag, findChangedFilesSince } = require('./git-utils')
|
||||||
function getLatestTag() {
|
|
||||||
try {
|
|
||||||
const res = cp.execSync('git describe --abbrev=0 --tags', { encoding: 'utf8', stdio: 'pipe' }).trim()
|
|
||||||
|
|
||||||
return res
|
|
||||||
} catch (e) {
|
|
||||||
if (e.stderr.match(/^fatal: (No names found|No tags can describe)/i)) {
|
|
||||||
// no tags found, let's just return the first commit
|
|
||||||
return cp.execSync('git rev-list --max-parents=0 HEAD', { encoding: 'utf8' }).trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function findChangedFilesSince(tag, until = 'HEAD') {
|
|
||||||
return cp.execSync(`git diff --name-only ${tag} ${until}`, { encoding: 'utf8', stdio: 'pipe' }).trim().split('\n')
|
|
||||||
}
|
|
||||||
|
|
||||||
getTsconfigFiles.cache = {}
|
getTsconfigFiles.cache = {}
|
||||||
|
|
||||||
|
@ -46,9 +28,11 @@ function isMeaningfulChange(pkg, path) {
|
||||||
if (getTsconfigFiles(pkg).indexOf(path) > -1) return true
|
if (getTsconfigFiles(pkg).indexOf(path) > -1) return true
|
||||||
|
|
||||||
// some magic heuristics stuff
|
// some magic heuristics stuff
|
||||||
if (path.match(/\.md$/i)) return false
|
if (path.match(/\.(md|\.test\.ts)$/i)) return false
|
||||||
if (path.match(/^\/(scripts|dist|tests|private)/i)) return false
|
if (path.match(/^\/(scripts|dist|tests|private)/i)) return false
|
||||||
|
|
||||||
|
console.log('[i] %s: %s is a meaningful change', pkg, path)
|
||||||
|
|
||||||
// to be safe
|
// to be safe
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
60
scripts/generate-changelog.js
Normal file
60
scripts/generate-changelog.js
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
const fs = require('fs')
|
||||||
|
const { getLatestTag, getCommitsSince, parseConventionalCommit, findChangedFilesSince } = require('./git-utils')
|
||||||
|
|
||||||
|
function generateChangelog(onlyPackages) {
|
||||||
|
const byPackage = {}
|
||||||
|
|
||||||
|
for (const commit of getCommitsSince(getLatestTag())) {
|
||||||
|
const parsed = parseConventionalCommit(commit.msg)
|
||||||
|
|
||||||
|
if (!parsed) {
|
||||||
|
console.warn('[warn] Failed to parse commit message: %s', commit.msg)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const { type, breaking } = parsed
|
||||||
|
|
||||||
|
if (!type || ['chore', 'ci', 'docs', 'test'].includes(type)) continue
|
||||||
|
|
||||||
|
const changed = findChangedFilesSince(`${commit.hash}~1`, commit.hash)
|
||||||
|
|
||||||
|
const line = `- ${commit.hash}: ${breaking ? '**❗ BREAKING** ' : ''}${commit.msg}`
|
||||||
|
|
||||||
|
for (const file of changed) {
|
||||||
|
if (!file.startsWith('packages/')) continue
|
||||||
|
const pkg = file.split('/')[1]
|
||||||
|
if (onlyPackages && !onlyPackages.includes(pkg)) continue
|
||||||
|
|
||||||
|
if (!byPackage[pkg]) byPackage[pkg] = {}
|
||||||
|
byPackage[pkg][commit.hash] = line
|
||||||
|
// console.log('including %s in %s because of %s', commit.hash, pkg, file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret = ''
|
||||||
|
|
||||||
|
for (const [pkg, lines] of Object.entries(byPackage)) {
|
||||||
|
ret += `### ${pkg}\n`
|
||||||
|
ret += Object.values(lines).join('\n')
|
||||||
|
ret += '\n\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
let onlyPackages = null
|
||||||
|
|
||||||
|
if (process.argv[2]) {
|
||||||
|
onlyPackages = process.argv[2].split(',')
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = generateChangelog(onlyPackages)
|
||||||
|
|
||||||
|
if (process.env.CI && process.env.GITHUB_OUTPUT) {
|
||||||
|
const delim = `---${require('crypto').randomUUID()}---${require('os').EOL}`
|
||||||
|
fs.appendFileSync(process.env.GITHUB_OUTPUT, `changelog<<${delim}${res}${delim}`)
|
||||||
|
} else {
|
||||||
|
console.log(res)
|
||||||
|
}
|
||||||
|
}
|
50
scripts/git-utils.js
Normal file
50
scripts/git-utils.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
const cp = require('child_process')
|
||||||
|
|
||||||
|
function getLatestTag() {
|
||||||
|
try {
|
||||||
|
const res = cp.execSync('git describe --abbrev=0 --tags', { encoding: 'utf8', stdio: 'pipe' }).trim()
|
||||||
|
|
||||||
|
return res
|
||||||
|
} catch (e) {
|
||||||
|
if (e.stderr.match(/^fatal: (No names found|No tags can describe)/i)) {
|
||||||
|
// no tags found, let's just return the first commit
|
||||||
|
return cp.execSync('git rev-list --max-parents=0 HEAD', { encoding: 'utf8' }).trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findChangedFilesSince(tag, until = 'HEAD') {
|
||||||
|
return cp.execSync(`git diff --name-only ${tag} ${until}`, { encoding: 'utf8', stdio: 'pipe' }).trim().split('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCommitsSince(tag, until = 'HEAD') {
|
||||||
|
return cp
|
||||||
|
.execSync(`git log --pretty="format:%H %s" ${tag}..${until}`, { encoding: 'utf8', stdio: 'pipe' })
|
||||||
|
.trim()
|
||||||
|
.split('\n')
|
||||||
|
.reverse()
|
||||||
|
.map((it) => {
|
||||||
|
const [hash, ...msg] = it.split(' ')
|
||||||
|
|
||||||
|
return { hash, msg: msg.join(' ') }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseConventionalCommit(msg) {
|
||||||
|
const match = msg.match(/^(\w+)(?:\(([^)]+)\))?(!?): (.+)$/)
|
||||||
|
|
||||||
|
if (!match) return null
|
||||||
|
|
||||||
|
const [, type, scope, breaking, subject] = match
|
||||||
|
|
||||||
|
return { type, scope, breaking: Boolean(breaking), subject }
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getLatestTag,
|
||||||
|
findChangedFilesSince,
|
||||||
|
getCommitsSince,
|
||||||
|
parseConventionalCommit,
|
||||||
|
}
|
Loading…
Reference in a new issue