# Semantic Release We use semantic release nearly everywhere. Here is a short description on how to write commit messages. ## Commits matter! We use semantic release (https://github.com/semantic-release/semantic-release) to automate releases. **BEST PRACTICE:** Develop (larger changes) on a seperate branch and merge it if you are ready. Either way, a commit body should have the following structure. Refer to the following docs: https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines ``` <type>(<scope>): <subject> <BLANK LINE> <body> <BLANK LINE> <footer> ``` ### Revert If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit hash`., where the hash is the SHA of the commit being reverted. ### Type Must be one of the following: - feat: A new feature - fix: A bug fix - docs: Documentation only changes - style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) - refactor: A code change that neither fixes a bug nor adds a feature - perf: A code change that improves performance - test: Adding missing or correcting existing tests - chore: Changes to the build process or auxiliary tools and libraries such as documentation generation ### Scope The scope could be anything specifying place of the commit change. ~~For example $location, $browser, $compile, $rootScope, ngHref, ngClick, ngView, etc...~~ In this case you could address the feature like `openservice` or `permission`. You can use `*` when the change affects more than a single scope. ### Subject The subject contains succinct description of the change: use the imperative, present tense: "change" not "changed" nor "changes" don't capitalize first letter no dot (.) at the end ### Body Just as in the subject, use the imperative, present tense: "change" not "changed" nor "changes". The body should include the motivation for the change and contrast this with previous behavior. ### Footer The footer should contain any information about Breaking Changes and is also the place to reference GitHub issues that this commit closes. Breaking Changes should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this. ## Sample GitHub Workflow configuration ```yml name: Docker Image CI on: push: branches: ["master"] pull_request: branches: ["master"] env: IMAGE_NAME: XXX LATEST_TAG: latest permissions: contents: write pages: write id-token: write jobs: release: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: persist-credentials: false - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 22 registry-url: "https://registry.npmjs.org/" - uses: pnpm/action-setup@v4 - name: Install dependencies run: pnpm install - name: Build the project run: pnpm run build - name: Archive dist folder #Use this to create a zip file with the distribution. This can be appended to the release assets. run: zip -r dist.zip dist - name: Semantic Release 🚀 id: semantic run: npx semantic-release --branches master env: GH_TOKEN: ${{ secrets.XXX }} NODE_AUTH_TOKEN: ${{ secrets.XXX }} outputs: new-release-published: ${{ steps.semantic.outputs.new-release-published }} new-release-version: ${{ steps.semantic.outputs.new-release-version }} new-release-git-tag: ${{ steps.semantic.outputs.new-release-git-tag }} publish: runs-on: ubuntu-latest needs: release if: github.ref == 'refs/heads/master' && github.event_name == 'push' && needs.release.outputs.new-release-published == 'true' steps: - uses: actions/checkout@v4 - name: Log in to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.XXX }} password: ${{ secrets.XXX }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.IMAGE_NAME }} - name: Build and push the Docker image uses: docker/build-push-action@v6 with: context: . file: ./Dockerfile sbom: true provenance: mode=max push: true tags: "${{env.IMAGE_NAME }}:${{ env.LATEST_TAG }},${{ env.IMAGE_NAME }}:${{ needs.release.outputs.new-release-version }}" ``` ## Package.json configuration ```json { ... "release": { "branches": ["master"], "repositoryUrl": "https://github.com/open-inc/xxx.git", "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator", "@semantic-release/changelog", { "path": "@semantic-release/github", "assets": [ { "path": "dist.zip", "name": "xxx-distribution-v${nextRelease.version}.zip" } ] }, "semantic-release-export-data" ], "prepare": [ "@semantic-release/changelog", "@semantic-release/npm", { "path": "@semantic-release/git", "assets": ["package.json", "pnpm-lock.json", "CHANGELOG.md"], "message": "chore(release): Release ${nextRelease.version} \n\n${nextRelease.notes}" } ] }, "dependencies": { ... "semantic-release": "^24.2.5" }, "devDependencies": { ... "@semantic-release/changelog": "^6.0.3", "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/exec": "^7.1.0", "@semantic-release/git": "^10.0.1", "@semantic-release/npm": "^12.0.1", "@semantic-release/github": "^11.0.3", "@semantic-release/release-notes-generator": "^14.0.3", "semantic-release-export-data": "^1.1.0", } } ```