From ebc2781d7aa518da6658c6acaf2c5cc2b92d1a73 Mon Sep 17 00:00:00 2001 From: cleverchuk Date: Fri, 14 Aug 2026 13:31:55 -0400 Subject: [PATCH] Internal - APM Java Slack release notification automation --- .github/scripts/create-jira-ticket.sh | 71 +++++++++++++++++++++++++++ .github/scripts/notify-slack.sh | 60 ++++++++++++++++++++++ .github/workflows/release.yml | 50 ++++++++++++++++++- 3 files changed, 180 insertions(+), 1 deletion(-) create mode 100755 .github/scripts/create-jira-ticket.sh create mode 100755 .github/scripts/notify-slack.sh diff --git a/.github/scripts/create-jira-ticket.sh b/.github/scripts/create-jira-ticket.sh new file mode 100755 index 00000000..02c7d92e --- /dev/null +++ b/.github/scripts/create-jira-ticket.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Creates a JIRA release ticket. +# +# Summary: "Java: Release Notes, " +# Description: the provided message text (matches the Slack release notification) +# +# Required environment variables: +# JIRA_BASE_URL - Base URL of the JIRA instance (e.g. https://company.atlassian.net) +# JIRA_USER_EMAIL - Email used for basic auth +# JIRA_API_TOKEN - JIRA API token +# JIRA_PROJECT_KEY - JIRA project key (e.g. NH) +# JIRA_ASSIGNEE_ID - Account ID of the assignee +# +# Usage: +# create-jira-ticket.sh +# +# Outputs: +# The JIRA ticket browse URL on stdout + +VERSION="${1:?version is required}" +DESCRIPTION="${2:?description is required}" + +: "${JIRA_BASE_URL:?JIRA_BASE_URL is required}" +: "${JIRA_USER_EMAIL:?JIRA_USER_EMAIL is required}" +: "${JIRA_API_TOKEN:?JIRA_API_TOKEN is required}" +: "${JIRA_PROJECT_KEY:?JIRA_PROJECT_KEY is required}" +: "${JIRA_ASSIGNEE_ID:?JIRA_ASSIGNEE_ID is required}" + +SUMMARY="Java: Release Notes, v${VERSION}" + +DESCRIPTION_ADF=$(jq -n --arg text "$DESCRIPTION" '{ + version: 1, + type: "doc", + content: [{ + type: "paragraph", + content: [{ type: "text", text: $text }] + }] +}') + +REQUEST_BODY=$(jq -n \ + --arg project "$JIRA_PROJECT_KEY" \ + --arg summary "$SUMMARY" \ + --arg assignee "$JIRA_ASSIGNEE_ID" \ + --argjson desc "$DESCRIPTION_ADF" \ + '{fields: { + project: {key: $project}, + summary: $summary, + issuetype: {name: "Story"}, + description: $desc, + components: [{name: "Instrumentation"}, {name: "Instrument Java"}], + labels: ["Documentation", "Documentation-APM", "Documentation_changelog-APMJava"], + assignee: {accountId: $assignee} + }}') + +RESPONSE=$(curl -sS \ + -X POST \ + -H "Content-Type: application/json" \ + -u "${JIRA_USER_EMAIL}:${JIRA_API_TOKEN}" \ + "${JIRA_BASE_URL}/rest/api/3/issue" \ + -d "$REQUEST_BODY") + +ISSUE_KEY=$(echo "$RESPONSE" | jq -r '.key // empty') +if [[ -z "$ISSUE_KEY" ]]; then + echo "❌ Failed to create JIRA ticket:" >&2 + echo "$RESPONSE" | jq '.' >&2 + exit 1 +fi + +echo "${JIRA_BASE_URL}/browse/${ISSUE_KEY}" diff --git a/.github/scripts/notify-slack.sh b/.github/scripts/notify-slack.sh new file mode 100755 index 00000000..efa46b20 --- /dev/null +++ b/.github/scripts/notify-slack.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Sends a release notification to Slack. +# +# Message format: +# - APM Java +# +# Jira: (only when jira-url is provided) +# +# Required environment variables: +# SLACK_TOKEN - Slack bot token used for authorization +# SLACK_CHANNEL - Channel id (or name) to post the message to +# +# Usage: +# notify-slack.sh [jira-url] + +VERSION="${1:?version is required}" +RELEASE_URL="${2:?release url is required}" +JIRA_URL="${3:-}" + +: "${SLACK_TOKEN:?SLACK_TOKEN is required}" +: "${SLACK_CHANNEL:?SLACK_CHANNEL is required}" + +RELEASE_DATE=$(date +"%B %-d, %Y") + +post_to_slack() { + local post_body="$1" + local response + + if ! response=$(curl -sfS https://slack.com/api/chat.postMessage \ + -H "Authorization: Bearer $SLACK_TOKEN" \ + -H 'Content-type: application/json; charset=utf-8' \ + -d "$post_body"); then + echo "❌ Slack API request failed" >&2 + exit 1 + fi + + if [[ "$(echo "$response" | jq -r '.ok')" != "true" ]]; then + echo "❌ Slack API error: $(echo "$response" | jq -r '.error // "unknown_error"')" >&2 + exit 1 + fi + + echo "$response" +} + +# Build the message text: " - APM Java " then the release url on a new line. +MESSAGE_TEXT="*${RELEASE_DATE} - APM Java ${VERSION}*"$'\n'"${RELEASE_URL}" +if [[ -n "$JIRA_URL" ]]; then + MESSAGE_TEXT+=$'\n'"*Jira:* ${JIRA_URL}" +fi + +# Use jq to safely construct the JSON payload (handles escaping of newlines/quotes). +POST_BODY=$(jq -n \ + --arg channel "$SLACK_CHANNEL" \ + --arg text "$MESSAGE_TEXT" \ + '{channel: $channel, text: $text}') + +post_to_slack "$POST_BODY" > /dev/null +echo "✅ Posted release notification to Slack channel" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5da000a3..20ffd080 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -86,7 +86,7 @@ jobs: VERSION=$(unzip -p agent/build/libs/solarwinds-apm-agent.jar META-INF/MANIFEST.MF | grep Implementation-Version | awk '{ print $2 }') VERSION=$(echo $VERSION | sed 's/[^a-z0-9.-]//g') # remove illegal characters echo "Current version is $VERSION" - + echo "version: $VERSION" > /tmp/version.txt SHA256=$(sha256sum agent/build/libs/solarwinds-apm-agent.jar | awk '{print $1}') echo "sha256: $SHA256" > /tmp/checksum.txt @@ -99,6 +99,54 @@ jobs: /tmp/checksum.txt \ agent/build/libs/solarwinds-apm-agent.jar \ libs/shared/src/main/resources/solarwinds-apm-config.json + release-notification: + needs: + - github_release + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Set agent version + id: set_version + run: | + TAG=$(gh release list --limit 1 --json tagName --jq '.[0].tagName') + VERSION=${TAG#v} + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Save release url + id: release + run: | + RELEASE_URL=$(gh release view "v${VERSION}" --json url --jq '.url') + echo "release_url=$RELEASE_URL" >> "$GITHUB_OUTPUT" + env: + VERSION: ${{ steps.set_version.outputs.version }} + + - name: Create JIRA Ticket + id: jira + continue-on-error: true + run: | + RELEASE_DATE=$(date +"%B %-d, %Y") + DESCRIPTION="${RELEASE_DATE} - APM Java ${VERSION}"$'\n'"${RELEASE_URL}" + JIRA_URL=$(.github/scripts/create-jira-ticket.sh "$VERSION" "$DESCRIPTION") + echo "jira_url=$JIRA_URL" >> "$GITHUB_OUTPUT" + env: + JIRA_BASE_URL: ${{ vars.JIRA_BASE_URL }} + JIRA_PROJECT_KEY: ${{ vars.JIRA_PROJECT_KEY }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_ASSIGNEE_ID: ${{ secrets.JIRA_ASSIGNEE_ID }} + VERSION: ${{ steps.set_version.outputs.version }} + RELEASE_URL: ${{ steps.release.outputs.release_url }} + + - name: Notify Slack + run: | + .github/scripts/notify-slack.sh "$VERSION" "$RELEASE_URL" "$JIRA_URL" + env: + SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }} + SLACK_CHANNEL: ${{ vars.SLACK_CHANNEL }} + RELEASE_URL: ${{ steps.release.outputs.release_url }} + JIRA_URL: ${{ steps.jira.outputs.jira_url }} + VERSION: ${{ steps.set_version.outputs.version }} s3-prod-upload: # this job uploads the jar and default config json to prod s3 if: inputs.run_s3_upload