Skip to content
Merged

Next #62

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
16aef37
add autorelease
ivictbor Jan 10, 2025
ba9b0ed
fix: build-live-demo-later
ivictbor Jan 11, 2025
1de2031
fix: add when event push
ivictbor Jan 11, 2025
3ff43dd
fix: add when event push
ivictbor Jan 11, 2025
5829036
fix: add rules for next publishing
ivictbor Jan 11, 2025
092393f
Merge branch 'main' into next
ivictbor Jan 11, 2025
be5ffcc
fix: integrate npm run build into semantic-release pipeline
ivictbor Jan 11, 2025
0fa1abb
fix: add @semantic-release/exec
ivictbor Jan 11, 2025
ae5300c
fix: index.ts typo
ivictbor Jan 12, 2025
281b16a
cleanup failToSlack.sh, exit from wp only if non 0
ivictbor Jan 12, 2025
f7e9ac3
wp.yml: try jus tbuild
ivictbor Jan 12, 2025
e9e4223
move build to buildRelease.sh
ivictbor Jan 13, 2025
f877031
run from right dir
ivictbor Jan 13, 2025
d70953c
try use bash
ivictbor Jan 13, 2025
b93ca34
try
ivictbor Jan 13, 2025
40dbdc5
try tee in all commands
ivictbor Jan 13, 2025
861db38
release 1.6.1
ivictbor Jan 13, 2025
1892f00
fix: test
ivictbor Jan 13, 2025
364c5ca
fix: add minValue and maxValue check on backend
Jan 13, 2025
889e27a
docs: add better notice about exection
ivictbor Jan 13, 2025
0cf7307
fix: test change
ivictbor Jan 13, 2025
2f190ca
fix: test change
ivictbor Jan 13, 2025
f1348ac
fix: test change
ivictbor Jan 13, 2025
33acbe5
fix: test change
ivictbor Jan 13, 2025
10486c5
fix: slack output message
ivictbor Jan 13, 2025
cabf2a3
debug, pring env in slack hook
ivictbor Jan 13, 2025
6f1cd8a
fix when in pipeline
ivictbor Jan 13, 2025
e0367e6
build without issues message
ivictbor Jan 13, 2025
12017e2
fix: try make a mistake
ivictbor Jan 13, 2025
4b214af
fix(build): broken npm run build detection
ivictbor Jan 13, 2025
a92c67d
add status filter
ivictbor Jan 13, 2025
304accc
fix error
ivictbor Jan 13, 2025
7089d26
Merge pull request #59 from devforth/min-max-backend-check
ivictbor Jan 13, 2025
0df1c0f
fix: add validation backend check
Jan 14, 2025
cff6ec1
Merge pull request #60 from devforth/validation-backend-check
ivictbor Jan 14, 2025
a8bee08
fix: change component used by filter inputs
Jan 14, 2025
91396a7
Merge pull request #61 from devforth/fix-filter-input-height
ivictbor Jan 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions adminforth/build.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

> adminforth@1.6.0 build
> rm -rf dist && tsc && npm run prepareDist && npm link


> adminforth@1.6.0 prepareDist
> cp -rL spa dist/


up to date, audited 3 packages in 7s

found 0 vulnerabilities
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,371 @@ In this post I will share our journey of how we did a transition from manual Cha

## Prehistory

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.
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.
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.

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.

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.

Git tags were applied only after release and there again was a chance that I will forget to push them to GitHub before release.
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.

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.

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.

## Transition

I will show a flow on empty fake repository
I will show a flow on empty fake small project to not overcomplicate things.
We will use minimal typescript package with `npm` and `semantic-release` to show how it works.

```
echo "# test-sem-release" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:devforth/test-sem-release.git
git push -u origin main
```

Now lets init new `npm package`:

```
git clone git@github.com:devforth/test-sem-release.git
npm init -y
npm install typescript --save-dev
npx tsc --init
```

Create a file `index.ts`:

```
export const greet = (name: string): string => {
return `Hello, ${name}!`;
};
```


In `package.json` add:

```
{
"name": "test-sem-release",
"name": "@devforth/test-sem-release",
//diff-add
"publishConfig": {
//diff-add
"access": "public"
//diff-add
},
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
//diff-add
"build": "tsc",
},
"author": "",
"license": "ISC",
"description": "",
//diff-add
"release": {
//diff-add
"branches": ["master", "next"]
"branches": [main", "next"],
//diff-add
"plugins": [
//diff-add
"@semantic-release/commit-analyzer",
//diff-add
"@semantic-release/release-notes-generator",
//diff-add
"@semantic-release/npm",
//diff-add
"@semantic-release/github"
//diff-add
],
//diff-add
}
}
```

Make sure name in package.json has your organisation name like mine `@devforth/` and you have access to publish packages to npmjs.com.


Also install `semantic-release`:

```
npm i -D semantic-release
```


## Connecting to CI

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/)

Create a file `.woodpecker.yml` in `deploy` directory:

```yaml title="deploy/.woodpecker.yml"
clone:
git:
image: woodpeckerci/plugin-git
settings:
partial: false
depth: 5

steps:
release:
image: node:22
when:
- event: push
volumes:
- /var/run/docker.sock:/var/run/docker.sock
commands:
- npm clean-install
- npm run build
- npm audit signatures
- npx semantic-release
secrets:
- GITHUB_TOKEN
- NPM_TOKEN
```

Go to Woodpecker, authorize via GitHub, click "Add repository", find your repository and add it.

Disable "Project settings" -> "Allow Pull Requests" because we do not want to trigger builds on PRs.
Enable "Project settings" -> "Trusted"
Enable "Project Visibility" -> "Public"

![Woodpecker project settings](image-3.png)


### Generating GitHub acces token

if your repo is in GitHub organisation, you need first enable access to personal access tokens for your organisation (if not yet done)

1. In the upper-right corner of GitHub, select your profile photo, then click Your organizations.
2. Next to the organization, click Settings.
3. In the left sidebar, under Personal access tokens, click Settings.
4. Select "Allow access via fine-grained personal access tokens"
5. We recommend setting "Require administrator approval"
6. "Allow access via personal access tokens (classic)"

Now go to your profile, click on "Settings" -> "Developer settings" -> "Personal access tokens" -> "Generate new token"

For permissions, select Contents: Read and Write
select Metadata: Read-only


In Woodpecker Go to settings, Secrets, Add Secret `GITHUB_TOKEN` and paste your token:

![Woodpecker Secrets](image.png)

In "Available at following events" select "Push, also you can select "Manual" if you want to trigger builds manually.


### Generating NPM token

Go to your npmjs.com account, click on "Profile Avatar" -> "Access Tokens" -> "Generate New Token" -> "New Granular Access Token".

Packages and scopes Permissions: Read and Write.

Add to Woodpecker as secret `NPM_TOKEN`


## Testing

For now we did not yet push anything to GitHub and did not publish anything to npm.

Lets do it now.


Just push your first commit as:


```
feat: initial commit
```

This will trigger semantic-release to do first release v1.0.0.

Now change something is index.ts and push it as fix

```
fix: fix greet function
```

This will trigger semantic-release to do release v1.0.1.


Now change something in index.ts and push it as feat

```
feat: add new function
```

This will trigger semantic-release to do release v1.1.0 because we added new feature, not just fixed something.


### Next distribution channel

Now we will show how to release to `next` channel.

```
git checkout -b next
```

Change something and push it as fix

```
fix: fix greet function in next
```

Commit it and push:

```
git push --set-upstream origin next
```

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.

Now lets add feature to next

```
feat: add new feature in next
```

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.

Noe lets merge `next` to `main` and push it:

```
git checkout main
git merge next
git push
```

This will trigger release `v1.2.0` because we merged `next` to `main` and it was a feature release.


## Slack notifications about releases

So now we have automatic releases with release notes on GitHub.
For our internal team we use Slack and we want to get notifications about releases there.

```
npm i -D semantic-release-slack-bot
```

Into "release" section of `package.json` add slack plugin:

```
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
"@semantic-release/github",
//diff-add
[
//diff-add
"semantic-release-slack-bot",
//diff-add
{
//diff-add
"notifyOnSuccess": true,
//diff-add
"notifyOnFail": true,
//diff-add
"slackIcon": ":package:",
//diff-add
"onSuccessTemplate": {
//diff-add
"text": "$npm_package_version has been released!"
//diff-add
},
//diff-add
"markdownReleaseNotes": true
//diff-add
}
//diff-add
]
//diff-add
],
```


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"

Add it to Woodpecker as secret `SLACK_WEBHOOK` environment variable.

Also add this secterd to `.woodpecker.yml`:

```yaml title="deploy/.woodpecker.yml"
secrets:
- GITHUB_TOKEN
- NPM_TOKEN
//diff-add
- SLACK_WEBHOOK
```



This will send notifications to Slack channel about succesfull releases when `npm run build` is done without errors.

## Slack notifications about build errors and unhappen releases


Create a file `failToSlack.sh` in `deploy` directory:

```sh title="deploy/failToSlack.sh"
#!/bin/sh

export BUILD_LOG=$(cat ../../adminforth/build.log)

COMMIT_SHORT_SHA=$(echo $CI_COMMIT_SHA | cut -c1-8)

MESSAGE="Broke \`$CI_REPO_NAME/$CI_COMMIT_BRANCH\` with commit (<$CI_COMMIT_URL|$COMMIT_SHORT_SHA>)."
CODE_BLOCK="\`\`\`$BUILD_LOG\n\`\`\`"

curl -s -X POST -H "Content-Type: application/json" -d '{
"username": "'"$CI_COMMIT_AUTHOR"'",
"icon_url": "'"$CI_COMMIT_AUTHOR_AVATAR"'",
"attachments": [
{
"mrkdwn_in": ["text", "pretext"],
"color": "#8A1C12",
"text": "'"$CODE_BLOCK"'",
"pretext": "'"$MESSAGE"'"
}
]
}' "$DEVELOPERS_SLACK_WEBHOOK"
```


Add `step` to `.woodpecker.yml`:

```yaml title="deploy/.woodpecker.yml"
steps:
release:
...
//diff-add
slack-on-failure:
//diff-add
image: curlimages/curl
//diff-add
when:
//diff-add
- status: failure
//diff-add
event: push
//diff-add
- event: push
//diff-add
commands:
//diff-add
- cd deploy && /bin/sh failToSlack.sh
//diff-add
secrets:
//diff-add
- DEVELOPERS_SLACK_WEBHOOK

```
Loading