In this blog post, I will share my journey of implementing an automated solution to publish release notes for service deployments to Confluence using Bitbucket Pipelines. This aimed to streamline our release process and ensure all relevant information was easily accessible to our team. By leveraging tools like Bitbucket and Confluence, we achieved a seamless integration that enhanced our workflow.
Step 1: Setting Up the Pipeline
We configured our Bitbucket pipeline to include a new step for publishing release notes. This involved writing a script in the bitbucket-pipelines.yml file to gather the necessary information (SHA, build number, and summary of updates).
Step 2: Generating Release Notes
We pulled the summary of updates from our commit messages and release notes. To ensure the quality of the summaries, we emphasized the importance of writing detailed and informative commit messages.
Step 3: Publishing to Confluence
Using the Confluence Cloud REST API, we automated the creation of Confluence pages. We made a parent page titled “Releases” and configured the script to publish a new page.
Repository Variables
We used several repository variables to keep sensitive information secure and make the script more maintainable:
- REPO_TOKEN: The token used to authenticate with the Bitbucket API.
- CONFLUENCE_USERNAME: The username for Confluence authentication.
- CONFLUENCE_TOKEN: The token for Confluence authentication.
- CONFLUENCE_SPACE_KEY: The key to the Confluence space where the release notes are published.
- CONFLUENCE_ANCESTOR_ID: The ID of the parent page under which new release notes pages are created.
- CONFLUENCE_API_URL: The URL of the Confluence API endpoint.
Script Details
Here is the script we used in our bitbucket-pipelines.yml file, along with an explanation of each part:
Step 1: Define the Pipeline Step
- step: &release-notes name: Publish Release Notes image: atlassian/default-image:3
- Step Name: The step is named “Publish Release Notes”.
- Docker Image: Uses the atlassian/default-image:3 Docker image for the environment.
Step 2: List Files
script: - ls -la /src/main/resources/
- List Files: The
ls -la
command lists the files in the specified directory to ensure the necessary files are present.
Step 3: Extract Release Number
- RELEASE_NUMBER=$(grep '{application_name}.version' /src/main/resources/application.properties | cut -d'=' -f2)
- Extract Release Number: The
grep
command extracts the release number from the application.properties file where the property{application_name}.version
should be present.
Step 4: Create Release Title
- RELEASE_TITLE="Release - $RELEASE_NUMBER Build- $BITBUCKET_BUILD_NUMBER Commit- $BITBUCKET_COMMIT"
- Create Release Title: Construct the release title using the release number, Bitbucket build number, and commit SHA.
Step 5: Get Commit Message
- COMMIT_MESSAGE=$(git log --format=%B -n 1 ${BITBUCKET_COMMIT})
- Get Commit Message: The git log command retrieves the commit message for the current commit.
Step 6: Check for Pull Request
- | if [[ $COMMIT_MESSAGE =~ pull\ request\ #([0-9]+) ]]; then PR_NUMBER=$(echo "$COMMIT_MESSAGE" | grep -o -E 'pull\ request\ \#([0-9]+)' | sed 's/[^0-9]*//g')
- Check for Pull Request: The script checks if the commit message contains a pull request number.
- Extract PR Number: If a pull request number is found, it is extracted using grep and sed.
Step 7: Fetch Pull Request Description
RAW_RESPONSE=$(wget --no-hsts -qO- --header="Authorization: Bearer $REPO_TOKEN" "https://api.bitbucket.org/2.0/repositories/$BITBUCKET_WORKSPACE/$BITBUCKET_REPO_SLUG/pullrequests/${PR_NUMBER}") PR_DESCRIPTION=$(echo "$RAW_RESPONSE" | jq -r '.description') echo "$PR_DESCRIPTION" > description.txt
- Fetch PR Description: Uses wget to fetch the pull request description from the Bitbucket API.
- Parse Description: Parses the description using jq and saves it to description.txt.
Step 8: Prepare JSON Data
AUTH_HEADER=$(echo -n "$CONFLUENCE_USERNAME:$CONFLUENCE_TOKEN" | base64 | tr -d '\n') JSON_DATA=$(jq -n --arg title "$RELEASE_TITLE" \ --arg type "page" \ --arg space_key "$CONFLUENCE_SPACE_KEY" \ --arg ancestor_id "$CONFLUENCE_ANCESTOR_ID" \ --rawfile pr_description description.txt \ '{ title: $title, type: $type, space: { key: $space_key }, ancestors: [{ id: ($ancestor_id | tonumber) }], body: { storage: { value: $pr_description, representation: "storage" } } }') echo "$JSON_DATA" > json_data.txt
- Prepare Auth Header: Encodes the Confluence username and token for authentication.
- Construct JSON Payload: Uses jq to construct the JSON payload for the Confluence API request.
- Save JSON Data: Saves the JSON payload to json_data.txt.
Step 9: Publish to Confluence
wget --no-hsts --method=POST --header="Content-Type: application/json" \ --header="Authorization: Basic $AUTH_HEADER" \ --body-file="json_data.txt" \ "$CONFLUENCE_API_URL" -q -O - if [[ $? -ne 0 ]]; then echo "HTTP request failed" exit 1 fi
- Send POST Request: This method uses wget to send a POST request to the Confluence API to create or update the release notes page.
- Error Handling: Checks if the HTTP request failed and exits with an error message if it did.
Script
# Service for publishing release notes - step: &release-notes name: Publish Release Notes image: atlassian/default-image:3 script: - ls -la /src/main/resources/ - RELEASE_NUMBER=$(grep '{application_name}.version' /src/main/resources/application.properties | cut -d'=' -f2) - RELEASE_TITLE="Release - $RELEASE_NUMBER Build- $BITBUCKET_BUILD_NUMBER Commit- $BITBUCKET_COMMIT" - COMMIT_MESSAGE=$(git log --format=%B -n 1 ${BITBUCKET_COMMIT}) - | if [[ $COMMIT_MESSAGE =~ pull\ request\ #([0-9]+) ]]; then PR_NUMBER=$(echo "$COMMIT_MESSAGE" | grep -o -E 'pull\ request\ \#([0-9]+)' | sed 's/[^0-9]*//g') RAW_RESPONSE=$(wget --no-hsts -qO- --header="Authorization: Bearer $REPO_TOKEN" "https://api.bitbucket.org/2.0/repositories/$BITBUCKET_WORKSPACE/$BITBUCKET_REPO_SLUG/pullrequests/${PR_NUMBER}") PR_DESCRIPTION=$(echo "$RAW_RESPONSE" | jq -r '.description') echo "$PR_DESCRIPTION" > description.txt AUTH_HEADER=$(echo -n "$CONFLUENCE_USERNAME:$CONFLUENCE_TOKEN" | base64 | tr -d '\n') JSON_DATA=$(jq -n --arg title "$RELEASE_TITLE" \ --arg type "page" \ --arg space_key "$CONFLUENCE_SPACE_KEY" \ --arg ancestor_id "$CONFLUENCE_ANCESTOR_ID" \ --rawfile pr_description description.txt \ '{ title: $title, type: $type, space: { key: $space_key }, ancestors: [{ id: ($ancestor_id | tonumber) }], body: { storage: { value: $pr_description, representation: "storage" } } }') echo "$JSON_DATA" > json_data.txt wget --no-hsts --method=POST --header="Content-Type: application/json" \ --header="Authorization: Basic $AUTH_HEADER" \ --body-file="json_data.txt" \ "$CONFLUENCE_API_URL" -q -O - if [[ $? -ne 0 ]]; then echo "HTTP request failed" exit 1 fi fi

Outcomes and Benefits
- The automation significantly reduced the manual effort required to publish release notes.
- The project improved our overall release process efficiency and documentation quality.
Conclusion
Automating the publication of release notes to Confluence using Bitbucket Pipelines has been a game-changer for our team. It has streamlined our release process and ensured all relevant information is readily available. I hope this blog post provides insights and inspiration for others looking to implement similar solutions.