← Files DatadogARCHIVED FILE
.github/workflows/release.yaml
3.82 KB · Nov 15, 2026 · 07:40 UTC
name: Release
on:
push:
branches:
# Stable releases land on main; preview releases land on
# preview-<slug> branches. Both fire this workflow to create the
# matching GitHub Release.
- main
- 'preview-*'
paths:
- '*-plugin/plugin.json'
- 'plugin.json'
- 'package.json'
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Extract version
id: version
run: |
MANIFEST=$(find . -maxdepth 2 -name plugin.json -path '*/.*-plugin/*' | head -1)
if [ -n "$MANIFEST" ]; then
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('${MANIFEST}','utf8')).version)")
elif [ -f plugin.json ]; then
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('plugin.json','utf8')).version)")
elif [ -f package.json ]; then
VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('package.json','utf8')).version)")
else
echo "No plugin.json or package.json found"
exit 1
fi
# Preview versions carry a -preview.<slug> semver prerelease
# suffix; flag those so the GitHub Release is marked accordingly.
if [[ "${VERSION}" == *-preview.* ]]; then
IS_PRERELEASE=true
else
IS_PRERELEASE=false
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT"
echo "is_prerelease=${IS_PRERELEASE}" >> "$GITHUB_OUTPUT"
echo "Detected version: ${VERSION} (prerelease=${IS_PRERELEASE})"
- name: Check if release already exists
id: check
run: |
# The default shell is `bash -e` without pipefail; without this, a
# failed lookup would be masked by wc/tr and read as "no release".
set -o pipefail
TAG="${{ steps.version.outputs.tag }}"
# Match on tag_name explicitly (not `gh release view`) so this also
# catches draft releases, which have a tag_name but no git tag ref
# yet — otherwise every push before the draft is published would
# create a duplicate draft for the same version.
# With --paginate, --jq runs once per page, so emit one line per
# matching release and count lines across all pages (gh rejects
# --slurp together with --jq).
MATCH=$(gh api "repos/${{ github.repository }}/releases?per_page=100" --paginate \
--jq '.[] | select(.tag_name == env.TAG) | .tag_name' | wc -l | tr -d ' ')
if [ "$MATCH" -gt 0 ]; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "Release ${TAG} already exists (or is already drafted), skipping"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ steps.version.outputs.tag }}
- name: Create draft release
if: steps.check.outputs.exists == 'false'
run: |
# Org policy blocks Actions from creating/pushing tags directly, so
# we create a draft release instead. GitHub doesn't create the git
# tag ref until a human publishes the draft, which is done under
# their own (bypass-exempt) identity rather than github-actions[bot].
TAG="${{ steps.version.outputs.tag }}"
ARGS="--title ${TAG} --generate-notes --draft --target ${{ github.sha }}"
if [ "${{ steps.version.outputs.is_prerelease }}" = "true" ]; then
ARGS="$ARGS --prerelease"
fi
gh release create "${TAG}" $ARGS
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SHA-256: 17afe1b3595b1e3000f780aabe81993cac9be2df762acac4f5dea748fc27524a