Skip to content

Commit 6e12548

Browse files
authored
feat: new release & publish GitHub workflow (#45)
1 parent 29f6beb commit 6e12548

File tree

3 files changed

+128
-109
lines changed

3 files changed

+128
-109
lines changed

.github/workflows/github-release-and-npm-package-publish.yml

Lines changed: 72 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -8,96 +8,85 @@ on:
88

99
jobs:
1010
check_conditions:
11-
name: Check conditions to create & release
11+
name: Check conditions to create & publish a release
1212
runs-on: ubuntu-latest
1313
permissions:
1414
contents: read
1515
outputs:
16-
do_release: ${{ steps.check_create_release_suffix.outputs.do_release }}
17-
do_release_changelog_generation: ${{ steps.check_create_release_suffix.outputs.do_release_changelog_generation }}
18-
do_release_version_bump: ${{ steps.check_create_release_suffix.outputs.do_release_version_bump }}
19-
do_release_version_bump_force_version: ${{ steps.check_create_release_suffix.outputs.do_release_version_bump_force_version }}
16+
success: ${{ steps.check_workflow_conditions.outputs.success }}
17+
appVersion: ${{ steps.check_workflow_conditions.outputs.appVersion }}
2018
steps:
2119
- name: Checkout the Codebase
2220
uses: actions/checkout@v4
2321
with:
24-
ref: main # branch to checkout
22+
# ref: main # branch to checkout, but we use the provided branch by the event
2523
fetch-depth: 0
2624

27-
- name: Check first line of commit message and search for commands `[rel-TYPE-CHANGELOG]`
28-
id: check_create_release_suffix
25+
# - name: Get `package.json` version
26+
# id: get_package_version
27+
# run: echo appVersion=$(node -p "require('./package.json').version") >> $GITHUB_OUTPUT
28+
29+
- name: Check workflow conditions to create a release on the current commit
30+
id: check_workflow_conditions
2931
uses: actions/github-script@v7
3032
with:
3133
script: |
32-
// context.sha === context.payload.head_commit.id
34+
const fs = require('fs').promises
35+
36+
const versionRegex = "\\d+\\.\\d+\\.\\d+(-rc\\.\\d+)?" // allowed: `1.0.0`, `1.0.0-rc.1`
37+
38+
// set default output that may be overwritten later
39+
setOutput("success", 0) // default: false
40+
41+
// helper function to set output with logging
42+
function setOutput(key, value) {
43+
console.dir(`:: set output: ${key}=${value}`)
44+
core.setOutput(key, value)
45+
}
46+
47+
// ==== commit message ====
3348
3449
// Get first line of last commit message
35-
const lastCommitMessage = context.payload.head_commit.message;
36-
const lastCommitMessageFirstLine = lastCommitMessage.split('\n')[0];
37-
38-
let do_release = "false";
39-
let do_release_version_bump = "false";
40-
let do_release_version_bump_force_version = "";
41-
let do_release_changelog_generation = "false";
42-
43-
const allowedTypes = [
44-
"none",
45-
// --------
46-
"auto",
47-
// --------
48-
"major",
49-
"minor",
50-
"patch",
51-
"premajor",
52-
"preminor",
53-
"prepatch",
54-
"prerelease",
55-
];
56-
57-
const allowedChangelog = [
58-
"y",
59-
"n",
60-
];
61-
62-
const regex = /\[rel-([a-z]+)-([a-z]+)\]/;
63-
const match = lastCommitMessageFirstLine.match(regex);
64-
65-
if (match) {
66-
do_release = "true";
67-
68-
const cmdType = match[1];
69-
const cmdChangelog = match[2];
70-
71-
if(!allowedTypes.includes(cmdType)){
72-
throw new Error(`Invalid release TYPE: ${cmdType}`);
73-
}
74-
if(!allowedChangelog.includes(cmdChangelog)){
75-
throw new Error(`Invalid release CHANGELOG: ${cmdChangelog}`);
76-
}
77-
78-
if(cmdType !== "none"){
79-
do_release_version_bump = "true";
80-
if(cmdType !== "auto"){
81-
do_release_version_bump_force_version = `--${cmdType}`;
82-
}
83-
}
84-
85-
if(cmdChangelog === "y"){
86-
do_release_changelog_generation = "true";
87-
}
50+
const lastCommitMessage = context?.payload?.head_commit.message ?? context?.payload?.commits[0]?.message
51+
const lastCommitMessageFirstLine = lastCommitMessage?.split('\n')[0] ?? ''
52+
53+
const regex_commitMessage = new RegExp(`^chore\\(release\\): v(?<version>${versionRegex}) \\(#\\d+\\)$`, "s")
54+
const match_commitMessage = lastCommitMessageFirstLine.match(regex_commitMessage)
55+
56+
if (!match_commitMessage || !match_commitMessage.groups?.version) {
57+
console.dir(`Invalid commit message: ${lastCommitMessageFirstLine}`)
58+
return
8859
}
8960
90-
console.dir(`Set output: do_release=${do_release}`);
91-
core.setOutput("do_release", do_release);
61+
const version_byCommitMessage = match_commitMessage.groups.version
9262
93-
console.dir(`Set output: do_release_version_bump=${do_release_version_bump}`);
94-
core.setOutput("do_release_version_bump", do_release_version_bump);
63+
// ==== version in `package.json` ====
64+
65+
const packageJson = await fs.readFile('package.json', 'utf8')
66+
const { version: version_byPackageJson } = JSON.parse(packageJson)
67+
68+
const regex_packageJson = new RegExp(`^(${versionRegex})$`, "s")
69+
const match_packageJson = version_byPackageJson.match(regex_packageJson)
70+
71+
if (!match_packageJson) {
72+
console.dir(`Invalid version in package.json: ${version_byPackageJson}`)
73+
return
74+
}
75+
76+
// ==== compare all versions ====
77+
78+
if (version_byCommitMessage !== version_byPackageJson) {
79+
console.dir(`Versions are not equal: ${version_byCommitMessage} (commit message) !== ${version_byPackageJson} (package.json)`)
80+
return
81+
}
9582
96-
console.dir(`Set output: do_release_version_bump_force_version=${do_release_version_bump_force_version}`);
97-
core.setOutput("do_release_version_bump_force_version", do_release_version_bump_force_version);
83+
// the versions are equal, so just take one of them
84+
const appVersion = version_byCommitMessage
9885
99-
console.dir(`Set output: do_release_changelog_generation=${do_release_changelog_generation}`);
100-
core.setOutput("do_release_changelog_generation", do_release_changelog_generation);
86+
// ==== set outputs ====
87+
88+
setOutput("appVersion", appVersion)
89+
setOutput("success", 1)
10190
10291
dependence-lint:
10392
name: Depend on Lint
@@ -107,7 +96,8 @@ jobs:
10796
needs:
10897
- check_conditions
10998
- dependence-lint
110-
if: needs.check_conditions.outputs.do_release == 'true'
99+
# only run if the conditions are met, and bc booleans are not supported, we use integers (false=0, true=1)
100+
if: needs.check_conditions.outputs.success == 1
111101
name: Create GitHub Release & NPM Publish
112102
runs-on: ubuntu-latest
113103
permissions:
@@ -116,7 +106,7 @@ jobs:
116106
- name: Checkout the Codebase
117107
uses: actions/checkout@v4
118108
with:
119-
ref: main # branch to checkout
109+
# ref: main # branch to checkout, but the workflow already only runs on `main`
120110
fetch-depth: 0
121111

122112
- name: Setup Node.js
@@ -134,54 +124,29 @@ jobs:
134124
git config --global user.name "github-actions[bot]"
135125
git config --global user.email "no-reply@todde.tv"
136126
127+
# do all code related stuff early to catch if something is wrong and it fails
128+
# TODO create a workflow like `Lint` to test install by lockfile and build
129+
137130
- name: Install dependencies
138131
run: pnpm install --frozen-lockfile
139132

140-
# - name: Get old `package.json` version
141-
# id: get_package_version_old
142-
# run: echo version=$(node -p "require('./package.json').version") >> $GITHUB_OUTPUT
143-
144-
- name: Bump `package.json` version depending on given TYPE from commit message
145-
if: needs.check_conditions.outputs.do_release_version_bump == 'true'
146-
# -from "v${{ steps.get_package_version_old.outputs.version }}"
147-
run: pnpm changelogen --bump ${{ needs.check_conditions.outputs.do_release_version_bump_force_version }} --no-commit --no-tag
148-
env:
149-
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
150-
151-
- name: Get new `package.json` version
152-
id: get_package_version_new
153-
run: echo version=$(node -p "require('./package.json').version") >> $GITHUB_OUTPUT
154-
155-
- name: Generate changelog from conventional commits
156-
if: needs.check_conditions.outputs.do_release_changelog_generation == 'true'
157-
# -from "v${{ steps.get_package_version_old.outputs.version }}"
158-
run: pnpm changelogen --output CHANGELOG.md -r "${{ steps.get_package_version_new.outputs.version }}" --no-commit --no-tag
159-
env:
160-
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
161-
162-
- name: Git add, commit & push changes made to `main` (potentially `package.json` & `CHANGELOG.md`)
163-
if: needs.check_conditions.outputs.do_release_version_bump == 'true' || needs.check_conditions.outputs.do_release_changelog_generation == 'true'
164-
run: |
165-
git add .
166-
git commit -m "chore(release): v${{ steps.get_package_version_new.outputs.version }}"
167-
git push origin main
133+
- name: Build the project
134+
run: pnpm run build
168135

169136
- name: Create a tag
170137
run: |
171-
git tag -a "v${{ steps.get_package_version_new.outputs.version }}" -m "Release v${{ steps.get_package_version_new.outputs.version }}"
138+
git tag -a "v${{ needs.check_conditions.outputs.appVersion }}" -m "Release v${{ needs.check_conditions.outputs.appVersion }}"
172139
git push origin --tags
173140
174141
- name: Sync tags with GitHub releases & create the new release
175142
# run: pnpm changelogen gh release all
176-
run: pnpm changelogen gh release "v${{ steps.get_package_version_new.outputs.version }}"
143+
run: pnpm changelogen gh release "v${{ needs.check_conditions.outputs.appVersion }}"
177144
env:
178145
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
179146

180-
# - name: Install dependencies
181-
# run: pnpm install --frozen-lockfile
182-
183-
- name: Build the project
184-
run: pnpm run build
147+
# # pack the project in a archive for publishing, e.g. `todde.tv-gltf-type-toolkit-1.0.0.tgz`
148+
# - name: Pack the project
149+
# run: pnpm pack
185150

186151
# - name: Publish package to NPM
187152
# if: github.ref == 'refs/heads/main'

README-dev.md

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,61 @@ Development VM ID from Thorsten for this project: `014`<br>
3030
6. Install dependencies: `pnpm i`
3131
7. Happy coding <3
3232

33-
## GitHub workflow commands inside commit messages
33+
## Create a release
34+
35+
When the variable `{VERSION}` is used in the following, then the exact string from field `version` of the
36+
`package.json` is meant, so to say the new version that the software will have after the release without
37+
prefixes like `v`.
38+
39+
1. Do not merge new things while the release is prepared, so stop it here until done.
40+
2. Check out branch `main` locally.
41+
3. Let us reset possible local disparities & test if the lockfile is healthy:
42+
```sh
43+
rm -rf node_modules/ dist/
44+
pnpm install --frozen-lockfile
45+
```
46+
4. Let us now find what the new version should be, therefore you have two ways to go:
47+
1. Variant 1: automatically detect new version depending on conventional commits of the commit messages since
48+
the old version
49+
1. bump the new version in `package.json` depending on conventional commits of the commit messages since the
50+
old version and generate a new entry in `CHANGELOG.md`.<br>
51+
(You could force a verion bump, but this is not what we whant. But see
52+
[Doc](https://github.com/unjs/changelogen?tab=readme-ov-file#cli-usage) for details.)
53+
```sh
54+
pnpm changelogen --no-commit --no-tag --bump [--{FORCE_VERSION}]
55+
```
56+
2. See the changes made in `package.json` and `CHANGELOG.md` and check if the version is reasonable.
57+
3. Reset the changelog bc we will generate it later again:
58+
```sh
59+
git checkout "CHANGELOG.md"
60+
```
61+
2. Variant 2: manually set a new version
62+
1. Open the `package.json` and write the wanted version in the `version` field.
63+
5. Use the following to create a changelog for the new version:
64+
```sh
65+
pnpm changelogen --output CHANGELOG.md -r "{VERSION}" --no-commit --no-tag
66+
```
67+
6. Create a branch with the name `rel/v{VERSION}` so that the made changes that are not committed yet are on there.
68+
7. Commit the made changes to the branch.<br>
69+
(You can use whatever commit message you want to use, e.g. `chore: prepare release v{VERSION}`.)
70+
8. Create a PR on GitHub for the branch to be merged to `main` with the title: `chore(release): v{VERSION}`
71+
9. Open `CHANGELOG.md`.
72+
1. Directly after the headline `## v{VERSION}` add the following with correctly changed content:
73+
```md
74+
Compare changes [from v{VERSION-old} to v{VERSION}](https://github.com/toddeTV/gltf-type-toolkit/compare/v{VERSION-old}...v{VERSION}) or see [full changelog](https://github.com/toddeTV/gltf-type-toolkit/blob/main/CHANGELOG.md).
75+
```
76+
2. In the `### 🏡 Chore` section (always the last before `### ❤️ Contributors`) add a new line at the end with the
77+
correct content for `{VERSION}` and `{PR_NUMBER}`:
78+
```md
79+
- **release:** v{VERSION} ([#{PR_NUMBER}](https://github.com/toddeTV/gltf-type-toolkit/pull/{PR_NUMBER}))
80+
```
81+
3. [optional] Change more things if needed (e.g. add description text at the top, ...)
82+
10. Commit the made changes to the branch.<br>
83+
(You can use whatever commit message you want to use, e.g. `chore: add current release PR to changelog`.)
84+
11. Squash & merge the GitHub PR to `main`.
85+
12. The GitHub workflow action defined in the file `github-release-and-npm-package-publish.yml` will create a
86+
GitHub Release & a NPM package publishing for the new version.
87+
13. Now you can continue merging new things, the release is done.
3488

3589
The commit message trigger must be present in the main commit message, so to say the first line, not the description.
3690

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@todde.tv/gltf-type-toolkit",
33
"type": "module",
4-
"version": "1.0.0",
4+
"version": "1.1.0-rc.0",
55
"packageManager": "pnpm@9.15.4",
66
"description": "This plugin generates type-safe glTF file representations in TypeScript and optimizes the loading and bundling of models in web projects, while being bundler-agnostic (Vite, Rollup, Webpack, esbuild, Rspack, ...).",
77
"author": "Thorsten Seyschab <business@todde.tv> (https://todde.tv/)",

0 commit comments

Comments
 (0)