Search code examples
javamavenbitbucketsemantic-release

How to integrate semantic-release with bitbucket (java project)


Can anyone provide an example/guide for bitbucket using semantic-release? A working repository for example? There is plenty of documentation on how to do it with github through actions, however for bitbucket the best I could find is this guide which is directed for node projects, but in my case I have a java-maven project, so a lot changes (like the fact I do not have a package.json), I will try to adapt that guide to my java project (and if manage to make it work answer this question with working config) but meanwhile I really appreciate any help.

EDIT: I will provide my configuration that works in github actions (all I need it to do for now is to generate the new release/tag with the semantic versioning, the pom.xml, changelog.md updates and the release notes, and that is what it is doing so far) so if anyone knows how to "translate it" to bitbucket pipelines that would also work for me:

github actions workflow .yml file:

name: TEST CONFIG 1

on:
  workflow_dispatch:
    branches:
      - main

jobs:
  semantic_release:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Setup Java
        uses: actions/setup-java@v4
        with:
          distribution: 'adopt'
          java-version: '11'
      - name: Install semantic-release
        run: npm install semantic-release @semantic-release/git @semantic-release/changelog @semantic-release/github @semantic-release/exec @semantic-release/commit-analyzer conventional-changelog-conventionalcommits
      - name: Semantic release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: npx semantic-release

.releaserc.json config file:

{
  "plugins": [
    [
      "@semantic-release/commit-analyzer",
      {
        "preset": "conventionalcommits",
        "releaseRules": [
          {
            "breaking": true,
            "release": "major"
          },
          {
            "type": "refactoring",
            "release": "patch"
          }
        ]
      }
    ],
    [
      "@semantic-release/release-notes-generator",
      {
        "preset": "conventionalcommits",
        "presetConfig": {
          "types": [
            {
              "type": "feat",
              "section": "New Feature(s) 🚀"
            },
            {
              "type": "fix",
              "section": "Bug Fix(es) 🐛️"
            },
            {
              "type": "docs",
              "section": "Documentation Changes 📝"
            },
            {
              "type": "refactor",
              "section": "Code Refactor 💅"
            },
            {
              "type": "test",
              "section": "Tests 📡️"
            },
            {
              "type": "perf",
              "section": "Performance Improvement(s) 🚄️"
            },
            {
              "type": "build",
              "section": "Build system 🛠️"
            },
            {
              "type": "refactoring",
              "section": "Refactoring \uD83D\uDEE0"
            }
          ]
        }
      }
    ],
    [
      "@semantic-release/github"
    ],
    [
      "@semantic-release/exec",
      {
        "prepareCmd": "mvn versions:set -DnewVersion=\"${nextRelease.version}\" && echo \"NEXT_VERSION=${nextRelease.version}, verifyReleaseCmd can also be used instead of prepareCmd\" >> build.env"
      }
    ],
    [
      "@semantic-release/changelog",
      {
        "changelogFile": "CHANGELOG.md",
        "changelogTitle": "# Semantic Versioning Changelog"
      }
    ],
    [
      "@semantic-release/git",
      {
        "assets": [
          "pom.xml",
          "service/pom.xml",
          "CHANGELOG.md"
        ],
        "message": "chore(release): ${nextRelease.version}"
      }
    ]
  ],
  "branches": [
    "main"
  ]
}

EDIT 2: Okay I managed to create a working config for bitbucket but it is only making the release/new tag generation and also the changelog, but I am not being able to run the mvn commands, because the pipeline says that mvn command not found, ofcourse I need to install mvn also but I can not figure out how to tell the pipeline I need maven and also node, if anybody can help me with that detail I appreciate, here is the configs:

bitbucket-pipelines.yml:

# This is an example Starter pipeline configuration
# Use a skeleton to build, test and deploy using manual and parallel steps
# -----
# You can specify a custom docker image from Docker Hub as your build environment.

image: node:latest

pipelines:
  default:
    - step:
        name: 'Deployment to Staging'
        deployment: staging
        script:
          - echo "Your deployment to staging script goes here..."
    - step:
        name: semantic_release
        trigger: 'manual'
        image: node:latest
        script:
          # Get an oauth access token using the client credentials, parsing out the token with jq.
          - apt-get update && apt-get install -y curl jq
          - >
            export BB_TOKEN=$(curl -s -X POST -u "${CLIENT_ID}:${CLIENT_SECRET}" \
              https://bitbucket.org/site/oauth2/access_token \
              -d grant_type=client_credentials -d scopes="repository"| jq --raw-output '.access_token')
          # Configure git to use the oauth token. This well happen when setting env variable BB_TOKEN
          - npm install semantic-release @semantic-release/git @semantic-release/changelog @semantic-release/exec @semantic-release/commit-analyzer conventional-changelog-conventionalcommits
          - npx semantic-release

.releaserc.json file (what makes the pipeline fail is in line 64 of this file, the mvn commands (at prepareCmd), but this is important because is what updates the pom files of the repository, this is used in the execution of npx semantic-release command of previous file (bitbucket-pipelines.yml)):

{
  "plugins": [
    [
      "@semantic-release/commit-analyzer",
      {
        "preset": "conventionalcommits",
        "releaseRules": [
          {
            "breaking": true,
            "release": "major"
          },
          {
            "type": "refactoring",
            "release": "patch"
          }
        ]
      }
    ],
    [
      "@semantic-release/release-notes-generator",
      {
        "preset": "conventionalcommits",
        "presetConfig": {
          "types": [
            {
              "type": "feat",
              "section": "New Feature(s) 🚀"
            },
            {
              "type": "fix",
              "section": "Bug Fix(es) 🐛️"
            },
            {
              "type": "docs",
              "section": "Documentation Changes 📝"
            },
            {
              "type": "refactor",
              "section": "Code Refactor 💅"
            },
            {
              "type": "test",
              "section": "Tests 📡️"
            },
            {
              "type": "perf",
              "section": "Performance Improvement(s) 🚄️"
            },
            {
              "type": "build",
              "section": "Build system 🛠️"
            },
            {
              "type": "refactoring",
              "section": "Refactoring \uD83D\uDEE0"
            }
          ]
        }
      }
    ],
    [
      "@semantic-release/exec",
      {
        "prepareCmd": "mvn versions:set -DnewVersion=\"${nextRelease.version}\" && echo \"NEXT_VERSION=${nextRelease.version}, verifyReleaseCmd can also be used instead of prepareCmd\" >> build.env"
      }
    ],
    [
      "@semantic-release/changelog",
      {
        "changelogFile": "CHANGELOG.md",
        "changelogTitle": "# Semantic Versioning Changelog"
      }
    ],
    [
      "@semantic-release/git",
      {
        "assets": [
          "pom.xml",
          "service/pom.xml",
          "CHANGELOG.md"
        ],
        "message": "chore(release): ${nextRelease.version}"
      }
    ]
  ],
  "branches": [
    "main"
  ]
}

Solution

  • Finally got a working config, going to explain each thing as much as I can step by step:

    1. First things first, you need a Docker image that has already installed maven, git, node and java, I created my own docker image which has all this (in my case I needed to make sure it was java 11 and node 20, the other stuff versions was not specified), here is the Dockerfile that I used to create this image:

      FROM ubuntu:20.04
      RUN apt-get update && apt-get install -y maven curl
      RUN apt-get install -y openjdk-11-jdk
      RUN curl -sL https://deb.nodesource.com/setup_20.x | bash -
      RUN apt-get install -y nodejs
      RUN apt-get -y install git

    2. Create your image from that Dockerfile and push it to Docker hub

    make sure you are logged in to your Dockerhub account with command docker login then standing at the same directory were you have located the previous Dockerfile (for example D:\IntelliJ\projects-bitbucket\demo)

    docker build -t yourdockerhubuser/thenameyouwantforyourimage .  
    docker push yourdockerhubuser/thenameyouwantforyourimage
    
    1. Now you have your own Docker image that has everything you need to execute the bitbucket pipeline, lets keep going, now lets configure the bitbucket-pipelines.yml file which will have a manual execution, here you should use the image that you pushed on the previous step (there is a lot of commented code because I was using it for debug purposes but I am leaving it there commented maybe you can find it useful sometime): Also in this config you will probably wonder what is CLIENT_ID and CLIENT_SECRET, that needs to be setup, this is covered in this guide https://medium.com/coding-spaghetti/npm-version-control-using-semantic-release-and-bitbucket-cloud-5294ac6b324b in the section Bitbucket Cloud Publishing to Own Repo using Semantic-Release just follow that section steps and comeback.
    # You have to use an image that has everything you need installed, that is why we created the image that we are using here in above steps
    image: yourdockerhubuser/thenameyouwantforyourimage
    
    pipelines:
      custom:
        manual:
          #- step:
              #name: build and test
              #script:
                #- mvn clean install
          - step:
              name: semantic_release
              #trigger: 'manual'
              script:
                - apt-get update
                #- node -v
                #- npm -v
                #- java -version
                #- mvn -version
                #- git --version
                # Get an oauth access token using the client credentials, parsing out the token with jq.
                - apt-get update && apt-get install -y curl jq
                - >
                  export BB_TOKEN=$(curl -s -X POST -u "${CLIENT_ID}:${CLIENT_SECRET}" \
                    https://bitbucket.org/site/oauth2/access_token \
                    -d grant_type=client_credentials -d scopes="repository"| jq --raw-output '.access_token')
                # Configure git to use the oauth token. This well happen when setting env variable BB_TOKEN
                - npm install semantic-release @semantic-release/git @semantic-release/changelog @semantic-release/exec @semantic-release/commit-analyzer conventional-changelog-conventionalcommits
                - npx semantic-release
    
    1. Setting up the .releaserc.json file at the root of your project: This file is responsible for overriding default configurations of the semantic-release tool, when you call the command npx semantic-release at the end of the bitbucket-pipelines.yml file it will use this config to know how to execute (keep in mind that in my case I had a child module called service, that is why in this file in the assets section I put the service/pom.xml, if that is not your case and you are working with a single module just remove that line, only leave your main pom.xml file and the changelog in the assets):
    {
      "plugins": [
        [
          "@semantic-release/commit-analyzer",
          {
            "preset": "conventionalcommits",
            "releaseRules": [
              {
                "breaking": true,
                "release": "major"
              },
              {
                "type": "refactoring",
                "release": "patch"
              },
              {
                "type": "refactor",
                "release": "patch"
              }
            ]
          }
        ],
        [
          "@semantic-release/release-notes-generator",
          {
            "preset": "conventionalcommits",
            "presetConfig": {
              "types": [
                {
                  "type": "feat",
                  "section": "New Feature(s) 🚀"
                },
                {
                  "type": "fix",
                  "section": "Bug Fix(es) 🐛️"
                },
                {
                  "type": "docs",
                  "section": "Documentation Changes 📝"
                },
                {
                  "type": "refactor",
                  "section": "Code Refactor 💅"
                },
                {
                  "type": "test",
                  "section": "Tests 📡️"
                },
                {
                  "type": "perf",
                  "section": "Performance Improvement(s) 🚄️"
                },
                {
                  "type": "build",
                  "section": "Build system 🛠️"
                },
                {
                  "type": "refactoring",
                  "section": "Refactoring \uD83D\uDEE0"
                }
              ]
            }
          }
        ],
        [
          "@semantic-release/exec",
          {
            "prepareCmd": "mvn versions:set -DnewVersion=\"${nextRelease.version}\" && mvn clean install"
          }
        ],
        [
          "@semantic-release/changelog",
          {
            "changelogFile": "CHANGELOG.md",
            "changelogTitle": "# Semantic Versioning Changelog"
          }
        ],
        [
          "@semantic-release/git",
          {
            "assets": [
              "pom.xml",
              "service/pom.xml",
              "CHANGELOG.md"
            ],
            "message": "chore(release): ${nextRelease.version} [skip ci]"
          }
        ]
      ],
      "branches": [
        "main"
      ]
    }
    
    
    1. At this point you just need to execute the pipeline in bitbucket and you should see it working, feel free to ask anything or feedback.