From f790da3abf55a496231c70b86afed044fbf75cc7 Mon Sep 17 00:00:00 2001 From: Shubham Gupta Date: Thu, 18 Jun 2026 15:26:17 +0530 Subject: [PATCH 1/2] ci: add release automation --- ci/release-finalize.sh | 99 ++++++++++++++++++++++++++++++++++++++++ ci/release-prepare.sh | 101 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 200 insertions(+) create mode 100755 ci/release-finalize.sh create mode 100755 ci/release-prepare.sh diff --git a/ci/release-finalize.sh b/ci/release-finalize.sh new file mode 100755 index 0000000..b8a2858 --- /dev/null +++ b/ci/release-finalize.sh @@ -0,0 +1,99 @@ +#!/bin/bash + +set -euo pipefail + +: "${TAG:?TAG is required (e.g. python-v1.41.0)}" +: "${LANGUAGE:?LANGUAGE is required (java, nodejs, or python)}" +: "${VERSION:?VERSION is required (e.g. 1.41.0)}" + +README="${LANGUAGE}/README.md" + +gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \ + --jq '.body' > /tmp/release_body.md + +python3 - "${README}" "${TAG}" "${VERSION}" /tmp/release_body.md <<'PYEOF' +import re +import sys + +readme_path = sys.argv[1] +tag = sys.argv[2] +version = sys.argv[3] +release_body_path = sys.argv[4] + +with open(release_body_path) as f: + body = f.read() + +def extract_table(text, heading_fragment): + lines = text.splitlines() + capture = False + table_lines = [] + for line in lines: + if heading_fragment.lower() in line.lower(): + capture = True + continue + if capture: + if line.startswith("##"): + break + if line.strip(): + table_lines.append(line) + return "\n".join(table_lines) + +amd64_table = extract_table(body, "AMD64 Lambda Layers List") +arm64_table = extract_table(body, "ARM64 Lambda Layers List") + +if not amd64_table: + print("ERROR: Could not extract AMD64 table from pre-release body", + file=sys.stderr) + sys.exit(1) +if not arm64_table: + print("ERROR: Could not extract ARM64 table from pre-release body", + file=sys.stderr) + sys.exit(1) + +with open(readme_path) as f: + content = f.read() + +content = re.sub( + r"unreleased version", + f"v{version}", + content, + count=1, +) + +def replace_section(text, heading, new_table): + lines = text.splitlines() + result = [] + skip = False + for line in lines: + if line.strip().startswith("##") and heading.lower() in line.lower(): + result.append(line) + result.append("") + result.append(new_table) + result.append("") + skip = True + continue + if skip: + if line.strip().startswith("##"): + skip = False + result.append(line) + continue + result.append(line) + return "\n".join(result) + +content = replace_section(content, "AMD64 Lambda Layers List", amd64_table) +content = replace_section(content, "ARM64 Lambda Layers List", arm64_table) + +content = re.sub( + r"releases/download/[^/]+/", + f"releases/download/{tag}/", + content, +) + +if not content.endswith("\n"): + content += "\n" + +with open(readme_path, "w") as f: + f.write(content) + +print(f"Updated {readme_path} with ARN tables for {tag}") +PYEOF diff --git a/ci/release-prepare.sh b/ci/release-prepare.sh new file mode 100755 index 0000000..06223dc --- /dev/null +++ b/ci/release-prepare.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +set -euo pipefail + +: "${LANGUAGE:?LANGUAGE is required (java, nodejs, or python)}" +: "${VERSION:?VERSION is required (e.g. 1.41.0)}" + +VERSION_DASHED="v${VERSION//./-}" +TAG="${LANGUAGE}-v${VERSION}" +RELEASE_BRANCH="release-${TAG}" +DATE="$(date +%Y-%m-%d)" + +LAYER_DATA="${LANGUAGE}/layer-data.sh" +TEMPLATE="${LANGUAGE}/sample-apps/template.yaml" + +OLD_VERSION_DASHED=$(grep '^VERSION=' "${LAYER_DATA}" | cut -d= -f2) + +# --- Update CHANGELOG.md --- + +cat > /tmp/changelog_block.md < Date: Thu, 18 Jun 2026 15:43:46 +0530 Subject: [PATCH 2/2] ci: simplify release process --- .github/workflows/release-finalize.yml | 12 ++----- .github/workflows/release-prepare.yml | 13 ++------ .github/workflows/release-tag.yml | 5 --- ci/release-finalize.sh | 11 +++++++ ci/release-prepare.sh | 43 +++++++++++++++++++++----- 5 files changed, 51 insertions(+), 33 deletions(-) diff --git a/.github/workflows/release-finalize.yml b/.github/workflows/release-finalize.yml index cbdd0e6..5fcc8bc 100644 --- a/.github/workflows/release-finalize.yml +++ b/.github/workflows/release-finalize.yml @@ -33,7 +33,6 @@ jobs: - uses: actions/checkout@v4 with: - persist-credentials: false ref: main fetch-depth: 0 @@ -76,18 +75,11 @@ jobs: "docs: update ${LANGUAGE} layer ARNs for ${TAG}" - name: Push release branch - env: - REMOTE: >- - https://x-access-token:${{ secrets.RELEASE_PAT - }}@github.com/${{ github.repository }} - run: | - git remote set-url origin "${REMOTE}" - git push origin \ - "${{ steps.parse.outputs.release_branch }}" + run: git push origin "${{ steps.parse.outputs.release_branch }}" - name: Create pull request env: - GH_TOKEN: ${{ secrets.RELEASE_PAT }} + GH_TOKEN: ${{ github.token }} TAG: ${{ steps.parse.outputs.tag }} LANGUAGE: ${{ steps.parse.outputs.language }} RELEASE_BRANCH: >- diff --git a/.github/workflows/release-prepare.yml b/.github/workflows/release-prepare.yml index 98031ee..255d362 100644 --- a/.github/workflows/release-prepare.yml +++ b/.github/workflows/release-prepare.yml @@ -44,7 +44,6 @@ jobs: - uses: actions/checkout@v4 with: - persist-credentials: false fetch-depth: 0 submodules: true @@ -87,17 +86,11 @@ jobs: git commit -m "${COMMIT_MSG}" - name: Push branch - env: - REMOTE: >- - https://x-access-token:${{ secrets.RELEASE_PAT - }}@github.com/${{ github.repository }} - run: | - git remote set-url origin "${REMOTE}" - git push origin "${BRANCH}" + run: git push origin "${BRANCH}" - name: Ensure release label exists env: - GH_TOKEN: ${{ secrets.RELEASE_PAT }} + GH_TOKEN: ${{ github.token }} run: | gh label create release \ --color "0075ca" \ @@ -106,7 +99,7 @@ jobs: - name: Create pull request env: - GH_TOKEN: ${{ secrets.RELEASE_PAT }} + GH_TOKEN: ${{ github.token }} run: | gh pr create \ --title "feat: prepare release ${LANGUAGE} v${VERSION}" \ diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index ddee1c7..3cbe39d 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -32,7 +32,6 @@ jobs: - uses: actions/checkout@v4 with: - persist-credentials: false ref: main fetch-depth: 0 @@ -45,10 +44,6 @@ jobs: - name: Create and push tag env: TAG: ${{ steps.parse.outputs.tag }} - REMOTE: >- - https://x-access-token:${{ secrets.RELEASE_PAT - }}@github.com/${{ github.repository }} run: | git tag -m "${TAG}" "${TAG}" - git remote set-url origin "${REMOTE}" git push origin "${TAG}" diff --git a/ci/release-finalize.sh b/ci/release-finalize.sh index b8a2858..5d82074 100755 --- a/ci/release-finalize.sh +++ b/ci/release-finalize.sh @@ -53,6 +53,11 @@ if not arm64_table: with open(readme_path) as f: content = f.read() +if "unreleased version" not in content: + print(f"ERROR: 'unreleased version' not found in {readme_path}", + file=sys.stderr) + sys.exit(1) + content = re.sub( r"unreleased version", f"v{version}", @@ -64,8 +69,10 @@ def replace_section(text, heading, new_table): lines = text.splitlines() result = [] skip = False + found = False for line in lines: if line.strip().startswith("##") and heading.lower() in line.lower(): + found = True result.append(line) result.append("") result.append(new_table) @@ -78,6 +85,10 @@ def replace_section(text, heading, new_table): result.append(line) continue result.append(line) + if not found: + print(f"ERROR: heading '{heading}' not found in {readme_path}", + file=sys.stderr) + sys.exit(1) return "\n".join(result) content = replace_section(content, "AMD64 Lambda Layers List", amd64_table) diff --git a/ci/release-prepare.sh b/ci/release-prepare.sh index 06223dc..bfb8332 100755 --- a/ci/release-prepare.sh +++ b/ci/release-prepare.sh @@ -13,7 +13,15 @@ DATE="$(date +%Y-%m-%d)" LAYER_DATA="${LANGUAGE}/layer-data.sh" TEMPLATE="${LANGUAGE}/sample-apps/template.yaml" +# Clean up .bak files on exit (including early exits) +cleanup() { find . -maxdepth 3 -name '*.bak' -delete; } +trap cleanup EXIT + OLD_VERSION_DASHED=$(grep '^VERSION=' "${LAYER_DATA}" | cut -d= -f2) +if [[ -z "${OLD_VERSION_DASHED}" ]]; then + echo "ERROR: could not extract VERSION from ${LAYER_DATA}" >&2 + exit 1 +fi # --- Update CHANGELOG.md --- @@ -30,8 +38,11 @@ cat > /tmp/changelog_block.md <&2 + exit 1 +fi sed -i.bak "/^All notable changes/r /tmp/changelog_block.md" CHANGELOG.md -rm -f CHANGELOG.md.bak # --- Update layer-data.sh --- @@ -41,17 +52,18 @@ sed -i.bak \ "s|tree/[^/]*/\{0,1\}${LANGUAGE}|tree/${RELEASE_BRANCH}/${LANGUAGE}|" \ "${LAYER_DATA}" -rm -f "${LAYER_DATA}.bak" - # --- Update template.yaml --- sed -i.bak "s|${OLD_VERSION_DASHED}|${VERSION_DASHED}|g" "${TEMPLATE}" -rm -f "${TEMPLATE}.bak" # --- Detect component versions from submodule --- COLLECTOR_VERSION=$(grep "go.opentelemetry.io/collector/otelcol v" \ opentelemetry-lambda/collector/go.mod | awk '{print $2}') +if [[ -z "${COLLECTOR_VERSION}" ]]; then + echo "ERROR: could not extract COLLECTOR_VERSION from collector/go.mod" >&2 + exit 1 +fi case "${LANGUAGE}" in python) @@ -61,16 +73,33 @@ case "${LANGUAGE}" in INSTRUMENTATION_VERSION=$(grep "^opentelemetry-distro==" \ opentelemetry-lambda/python/src/otel/otel_sdk/requirements.txt \ | cut -d= -f3) + if [[ -z "${SDK_VERSION}" ]]; then + echo "ERROR: could not extract opentelemetry-sdk version from requirements.txt" >&2 + exit 1 + fi + if [[ -z "${INSTRUMENTATION_VERSION}" ]]; then + echo "ERROR: could not extract opentelemetry-distro version from requirements.txt" >&2 + exit 1 + fi ;; nodejs) - SDK_VERSION=v$(grep -A2 '"node_modules/@opentelemetry/sdk-trace-node"' \ + # Extract version from the resolved field which is stable across npm lock formats + SDK_VERSION=v$(grep -A5 '"node_modules/@opentelemetry/sdk-trace-node"' \ opentelemetry-lambda/nodejs/package-lock.json \ - | grep '"version"' | grep -o '[0-9][0-9.]*') + | grep '"version"' | grep -o '[0-9][0-9.]*' | head -1) + if [[ "${SDK_VERSION}" == "v" ]]; then + echo "ERROR: could not extract @opentelemetry/sdk-trace-node version from package-lock.json" >&2 + exit 1 + fi ;; java) SDK_VERSION=$(grep 'opentelemetry-javaagent:' \ opentelemetry-lambda/java/dependencyManagement/build.gradle.kts \ | grep -o '[0-9][0-9.]*' | head -1) + if [[ -z "${SDK_VERSION}" ]]; then + echo "ERROR: could not extract opentelemetry-javaagent version from build.gradle.kts" >&2 + exit 1 + fi ;; esac @@ -96,6 +125,4 @@ case "${LANGUAGE}" in ;; esac -rm -f README.md.bak - echo "Release preparation complete for ${TAG}"