You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: adminforth/documentation/blog/2025-01-09-how-adminforth-manages-version/index.md
+341-5Lines changed: 341 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -11,35 +11,371 @@ In this post I will share our journey of how we did a transition from manual Cha
11
11
12
12
## Prehistory
13
13
14
-
Before 1.6.0 AdminForth was using manual ChangeLog. We were reviwing PRs, merged them all to `main` branch and there did manually npm release. We were constantly releasing to next pre-release version and used it internally on our projets for testing. Once we collected enough features and fixes, we were doing a release to `latest` version.
14
+
Before 1.6.0 AdminForth was using manual ChangeLog. We were reviwing PRs, merged them all to `main` branch and there did manually npm release. We were constantly releasing to `next` pre-release version from `main` and used `next` it internally on our projets for testing. Once we collected enough features and fixes, we were doing a release to `latest` version, and at this time we did release documentation.
15
+
ChangeLog included only main "latest" chain of versions, so while we releasing to `next` we added items under one version in ChangeLog. So user was not able to distinguish `1.5.0-next.0` from `1.5.0-next.1` in ChangeLog.
16
+
17
+
Anyway this was a pretty good approach, but it was hard to maintain ChangeLog: first you have to write commit message, then write same message in ChangeLog. And from time to time we were missing updating ChangeLog at all.
18
+
19
+
Also since release was manual from my PC there was a chance that I will forget to push tags to GitHub and release already happened. And chance that I will forget to push ChangeLog to GitHub.
20
+
21
+
Git tags were applied only after release and there again was a chance that I will forget to push them to GitHub before release.
22
+
So only one reliabile way to check what is difference in source code between versions was to use https://npmdiff.dev/ and not rely on git and ChangeLog.
23
+
24
+
Another thing is documentation. If I added something to documentation and decided to release it, there was a chance that I will release items for `next` version which are not yet in `latest` version. But this was easily solvable by maintaining `next` and `latest` branches instead of doing `next` development in `main` branch. In the end we switched to this approach.
25
+
26
+
Another thing - structure of repository. Historically for faster development in dev demo, we added all plugins into one repository. This was good for development(and very bad when count of plugins increased), and very bad for release process. Every plugin had its own version and its own ChangeLog. So we had to enter every plugin folder, do release, and push ChangeLog to GitHub. This was very time consuming and error-prone. It started to be obvious that we need to split plugins to separate repositories what was done now.
15
27
16
28
## Transition
17
29
18
-
I will show a flow on empty fake repository
30
+
I will show a flow on empty fake small project to not overcomplicate things.
31
+
We will use minimal typescript package with `npm` and `semantic-release` to show how it works.
"test": "echo \"Error: no test specified\" && exit 1"
75
+
//diff-add
76
+
"build": "tsc",
34
77
},
35
78
"author": "",
36
79
"license": "ISC",
37
80
"description": "",
38
81
//diff-add
39
82
"release": {
40
83
//diff-add
41
-
"branches": ["master", "next"]
84
+
"branches": [main", "next"],
85
+
//diff-add
86
+
"plugins": [
87
+
//diff-add
88
+
"@semantic-release/commit-analyzer",
89
+
//diff-add
90
+
"@semantic-release/release-notes-generator",
91
+
//diff-add
92
+
"@semantic-release/npm",
93
+
//diff-add
94
+
"@semantic-release/github"
95
+
//diff-add
96
+
],
42
97
//diff-add
43
98
}
44
99
}
100
+
```
101
+
102
+
Make sure name in package.json has your organisation name like mine `@devforth/` and you have access to publish packages to npmjs.com.
103
+
104
+
105
+
Also install `semantic-release`:
106
+
107
+
```
108
+
npm i -D semantic-release
109
+
```
110
+
111
+
112
+
## Connecting to CI
113
+
114
+
We will use Woodpecker CI for this example. Woodpecker is a free and open-source CI/CD tool that you can install to your own server / VPS and will not need to pay only for server. No limits on pipelines, users, repositories, etc. If you want to try it, we have [Woodpecker installation guide](https://devforth.io/blog/step-by-step-guide-to-modern-secure-ci-setup/)
115
+
116
+
Create a file `.woodpecker.yml` in `deploy` directory:
117
+
118
+
```yaml title="deploy/.woodpecker.yml"
119
+
clone:
120
+
git:
121
+
image: woodpeckerci/plugin-git
122
+
settings:
123
+
partial: false
124
+
depth: 5
125
+
126
+
steps:
127
+
release:
128
+
image: node:22
129
+
when:
130
+
- event: push
131
+
volumes:
132
+
- /var/run/docker.sock:/var/run/docker.sock
133
+
commands:
134
+
- npm clean-install
135
+
- npm run build
136
+
- npm audit signatures
137
+
- npx semantic-release
138
+
secrets:
139
+
- GITHUB_TOKEN
140
+
- NPM_TOKEN
141
+
```
142
+
143
+
Go to Woodpecker, authorize via GitHub, click "Add repository", find your repository and add it.
144
+
145
+
Disable "Project settings" -> "Allow Pull Requests" because we do not want to trigger builds on PRs.
146
+
Enable "Project settings" -> "Trusted"
147
+
Enable "Project Visibility" -> "Public"
148
+
149
+

150
+
151
+
152
+
### Generating GitHub acces token
153
+
154
+
if your repo is in GitHub organisation, you need first enable access to personal access tokens for your organisation (if not yet done)
155
+
156
+
1. In the upper-right corner of GitHub, select your profile photo, then click Your organizations.
157
+
2. Next to the organization, click Settings.
158
+
3. In the left sidebar, under Personal access tokens, click Settings.
159
+
4. Select "Allow access via fine-grained personal access tokens"
160
+
5. We recommend setting "Require administrator approval"
161
+
6. "Allow access via personal access tokens (classic)"
162
+
163
+
Now go to your profile, click on "Settings" -> "Developer settings" -> "Personal access tokens" -> "Generate new token"
164
+
165
+
For permissions, select Contents: Read and Write
166
+
select Metadata: Read-only
167
+
168
+
169
+
In Woodpecker Go to settings, Secrets, Add Secret `GITHUB_TOKEN` and paste your token:
170
+
171
+

172
+
173
+
In "Available at following events" select "Push, also you can select "Manual" if you want to trigger builds manually.
174
+
175
+
176
+
### Generating NPM token
177
+
178
+
Go to your npmjs.com account, click on "Profile Avatar" -> "Access Tokens" -> "Generate New Token" -> "New Granular Access Token".
179
+
180
+
Packages and scopes Permissions: Read and Write.
181
+
182
+
Add to Woodpecker as secret `NPM_TOKEN`
183
+
184
+
185
+
## Testing
186
+
187
+
For now we did not yet push anything to GitHub and did not publish anything to npm.
188
+
189
+
Lets do it now.
190
+
191
+
192
+
Just push your first commit as:
193
+
194
+
195
+
```
196
+
feat: initial commit
197
+
```
198
+
199
+
This will trigger semantic-release to do first release v1.0.0.
200
+
201
+
Now change something is index.ts and push it as fix
202
+
203
+
```
204
+
fix: fix greet function
205
+
```
206
+
207
+
This will trigger semantic-release to do release v1.0.1.
208
+
209
+
210
+
Now change something in index.ts and push it as feat
211
+
212
+
```
213
+
feat: add new function
214
+
```
215
+
216
+
This will trigger semantic-release to do release v1.1.0 because we added new feature, not just fixed something.
217
+
218
+
219
+
### Next distribution channel
220
+
221
+
Now we will show how to release to `next` channel.
222
+
223
+
```
224
+
git checkout -b next
225
+
```
226
+
227
+
Change something and push it as fix
228
+
229
+
```
230
+
fix: fix greet function in next
231
+
```
232
+
233
+
Commit it and push:
234
+
235
+
```
236
+
git push --set-upstream origin next
237
+
```
238
+
239
+
This will trigger semantic-release to do release `v1.1.1-next.1`. Please not that it bumped patch version because we are in `next` channel.
240
+
241
+
Now lets add feature to next
242
+
243
+
```
244
+
feat: add new feature in next
245
+
```
246
+
247
+
It will trigger release `v1.2.0-next.1` because we added new feature and minor version was bumped. Please not that next number started from 1 again.
248
+
249
+
Noe lets merge `next` to `main` and push it:
250
+
251
+
```
252
+
git checkout main
253
+
git merge next
254
+
git push
255
+
```
256
+
257
+
This will trigger release `v1.2.0` because we merged `next` to `main` and it was a feature release.
258
+
259
+
260
+
## Slack notifications about releases
261
+
262
+
So now we have automatic releases with release notes on GitHub.
263
+
For our internal team we use Slack and we want to get notifications about releases there.
264
+
265
+
```
266
+
npm i -D semantic-release-slack-bot
267
+
```
268
+
269
+
Into "release" section of `package.json` add slack plugin:
270
+
271
+
```
272
+
"plugins": [
273
+
"@semantic-release/commit-analyzer",
274
+
"@semantic-release/release-notes-generator",
275
+
"@semantic-release/npm",
276
+
"@semantic-release/github",
277
+
//diff-add
278
+
[
279
+
//diff-add
280
+
"semantic-release-slack-bot",
281
+
//diff-add
282
+
{
283
+
//diff-add
284
+
"notifyOnSuccess": true,
285
+
//diff-add
286
+
"notifyOnFail": true,
287
+
//diff-add
288
+
"slackIcon": ":package:",
289
+
//diff-add
290
+
"onSuccessTemplate": {
291
+
//diff-add
292
+
"text": "$npm_package_version has been released!"
293
+
//diff-add
294
+
},
295
+
//diff-add
296
+
"markdownReleaseNotes": true
297
+
//diff-add
298
+
}
299
+
//diff-add
300
+
]
301
+
//diff-add
302
+
],
303
+
```
304
+
305
+
306
+
Also create channel in Slack, click on channel name, "Integrations" -> "Add an App" -> "Incoming Webhooks" -> "Add to Slack" -> "Add Incoming Webhook to Workspace" -> "Add to Slack" -> "Copy Webhook URL"
307
+
308
+
Add it to Woodpecker as secret `SLACK_WEBHOOK` environment variable.
309
+
310
+
Also add this secterd to `.woodpecker.yml`:
311
+
312
+
```yaml title="deploy/.woodpecker.yml"
313
+
secrets:
314
+
- GITHUB_TOKEN
315
+
- NPM_TOKEN
316
+
//diff-add
317
+
- SLACK_WEBHOOK
318
+
```
319
+
320
+
321
+
322
+
This will send notifications to Slack channel about succesfull releases when `npm run build` is done without errors.
323
+
324
+
## Slack notifications about build errors and unhappen releases
325
+
326
+
327
+
Create a file `failToSlack.sh` in `deploy` directory:
0 commit comments