From 39b50c7a372b3e9d232f5daa6ec884e4fe0e5105 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Tue, 14 Oct 2025 09:07:17 +0200 Subject: [PATCH 1/5] build: add release and bugfix action(s) --- .github/actions/create-tag/action.yml | 24 ++++ .github/actions/normalize-version/action.yml | 27 +++++ .github/workflows/ci_pipeline.yml | 2 +- .github/workflows/prepare_bugfix.yml | 72 ++++++++++++ .github/workflows/release.yml | 70 ++++++++++++ .github/workflows/release_bugfix.yml | 110 +++++++++++++++++++ 6 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 .github/actions/create-tag/action.yml create mode 100644 .github/actions/normalize-version/action.yml create mode 100644 .github/workflows/prepare_bugfix.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/release_bugfix.yml diff --git a/.github/actions/create-tag/action.yml b/.github/actions/create-tag/action.yml new file mode 100644 index 0000000..a7c1134 --- /dev/null +++ b/.github/actions/create-tag/action.yml @@ -0,0 +1,24 @@ +name: 'Create and Push Tag' +description: 'Creates an annotated tag and pushes it to the repository' +inputs: + tag: + description: 'Tag name to create' + required: true +runs: + using: 'composite' + steps: + - name: Check if tag exists + shell: bash + run: | + if git rev-parse "${{ inputs.tag }}" >/dev/null 2>&1; then + echo "Error: Tag ${{ inputs.tag }} already exists" + exit 1 + fi + + - name: Create and push tag + shell: bash + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "${{ inputs.tag }}" -m "Release ${{ inputs.tag }}" + git push origin "${{ inputs.tag }}" diff --git a/.github/actions/normalize-version/action.yml b/.github/actions/normalize-version/action.yml new file mode 100644 index 0000000..0aebd8a --- /dev/null +++ b/.github/actions/normalize-version/action.yml @@ -0,0 +1,27 @@ +name: 'Normalize Version' +description: 'Normalizes a version string by removing v prefix and creating tag format' +inputs: + version: + description: 'Version string to normalize (e.g., 1.0.0 or v1.0.0)' + required: true +outputs: + version: + description: 'Normalized version without v prefix' + value: ${{ steps.normalize.outputs.version }} + tag: + description: 'Tag name with v prefix' + value: ${{ steps.normalize.outputs.tag }} +runs: + using: 'composite' + steps: + - name: Normalize version + id: normalize + shell: bash + run: | + version="${{ inputs.version }}" + # Remove 'v' prefix if present + version="${version#v}" + # Add 'v' prefix for tag + tag="v${version}" + echo "version=$version" >> $GITHUB_OUTPUT + echo "tag=$tag" >> $GITHUB_OUTPUT diff --git a/.github/workflows/ci_pipeline.yml b/.github/workflows/ci_pipeline.yml index 88caaf0..ca804e6 100644 --- a/.github/workflows/ci_pipeline.yml +++ b/.github/workflows/ci_pipeline.yml @@ -2,7 +2,7 @@ name: CI on: push: - branches: [ main ] + branches: [ main, bugfix/* ] pull_request: branches: [ main ] diff --git a/.github/workflows/prepare_bugfix.yml b/.github/workflows/prepare_bugfix.yml new file mode 100644 index 0000000..8ef23e6 --- /dev/null +++ b/.github/workflows/prepare_bugfix.yml @@ -0,0 +1,72 @@ +name: Prepare Bugfix Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Bugfix version (e.g., 1.0.1 or v1.0.1)' + required: true + type: string + +jobs: + create-bugfix-branch: + name: Create Bugfix Branch + runs-on: ubuntu-latest + + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate not on main branch + run: | + current_branch="${{ github.ref_name }}" + if [ "$current_branch" = "main" ]; then + echo "Error: Cannot create bugfix branch from main branch. Please select another branch or a tag" + exit 1 + fi + echo "Creating bugfix branch from: $current_branch" + + - name: Normalize version and validate + id: normalize_version + run: | + version="${{ github.event.inputs.version }}" + # Remove 'v' prefix if present + version="${version#v}" + + # Validate semver format (basic check) + if ! echo "$version" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$'; then + echo "Error: Invalid version format. Expected semver format (e.g., 1.0.1)" + exit 1 + fi + + # Extract patch version + patch_version=$(echo "$version" | cut -d. -f3 | cut -d- -f1) + + # Warn if patch version is 0 + if [ "$patch_version" = "0" ]; then + echo "::warning::Patch version is 0. Bugfix branches typically have a non-zero patch version (e.g., 1.0.1, not 1.0.0)" + fi + + branch_name="bugfix/$version" + echo "version=$version" >> $GITHUB_OUTPUT + echo "branch_name=$branch_name" >> $GITHUB_OUTPUT + + - name: Check if branch exists + run: | + if git ls-remote --heads origin "${{ steps.normalize_version.outputs.branch_name }}" | grep -q "${{ steps.normalize_version.outputs.branch_name }}"; then + echo "Error: Branch ${{ steps.normalize_version.outputs.branch_name }} already exists" + exit 1 + fi + + - name: Create and push bugfix branch + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git checkout -b "${{ steps.normalize_version.outputs.branch_name }}" + git push -u origin "${{ steps.normalize_version.outputs.branch_name }}" + echo "✅ Created bugfix branch: ${{ steps.normalize_version.outputs.branch_name }}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..adee473 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,70 @@ +name: Create Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Release version (e.g., 1.0.0 or v1.0.0)' + required: true + type: string + +jobs: + create-tag: + name: Create Tag + runs-on: ubuntu-latest + + permissions: + contents: write + + outputs: + version: ${{ steps.normalize_version.outputs.version }} + tag: ${{ steps.normalize_version.outputs.tag }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Normalize version + id: normalize_version + uses: ./.github/actions/normalize-version + with: + version: ${{ github.event.inputs.version }} + + - name: Create and push tag + uses: ./.github/actions/create-tag + with: + tag: ${{ steps.normalize_version.outputs.tag }} + + create-release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: create-tag + + permissions: + contents: write + + steps: + - name: Create Release + uses: ncipollo/release-action@v1 + with: + tag: ${{ needs.create-tag.outputs.tag }} + name: Release ${{ needs.create-tag.outputs.version }} + body: | + ## Installation + + To use this version in your Go project, run: + + ```bash + go get github.com/${{ github.repository }}@${{ needs.create-tag.outputs.tag }} + ``` + + Or add it to your `go.mod`: + + ```go + require github.com/${{ github.repository }} ${{ needs.create-tag.outputs.tag }} + ``` + generateReleaseNotes: true + draft: false + prerelease: false \ No newline at end of file diff --git a/.github/workflows/release_bugfix.yml b/.github/workflows/release_bugfix.yml new file mode 100644 index 0000000..f065658 --- /dev/null +++ b/.github/workflows/release_bugfix.yml @@ -0,0 +1,110 @@ +name: Release Bugfix + +on: + workflow_dispatch: + +jobs: + create-tag: + name: Create Tag + runs-on: ubuntu-latest + + permissions: + contents: write + + outputs: + version: ${{ steps.extract_version.outputs.version }} + tag: ${{ steps.extract_version.outputs.tag }} + is_latest: ${{ steps.check_latest.outputs.is_latest }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate bugfix branch + run: | + current_branch="${{ github.ref_name }}" + if [[ ! "$current_branch" =~ ^bugfix/ ]]; then + echo "Error: This workflow must be run from a bugfix/* branch" + echo "Current branch: $current_branch" + exit 1 + fi + echo "Running on bugfix branch: $current_branch" + + - name: Extract version from branch name + id: extract_version + run: | + current_branch="${{ github.ref_name }}" + # Extract version from bugfix/X.Y.Z format + version="${current_branch#bugfix/}" + + # Validate semver format + if ! echo "$version" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$'; then + echo "Error: Invalid version format in branch name. Expected bugfix/X.Y.Z" + exit 1 + fi + + tag="v${version}" + echo "version=$version" >> $GITHUB_OUTPUT + echo "tag=$tag" >> $GITHUB_OUTPUT + echo "Extracted version: $version" + + - name: Check if this should be latest release + id: check_latest + run: | + current_version="${{ steps.extract_version.outputs.version }}" + + # Get all tags and find the highest version + highest_version=$(git tag -l 'v*' | sed 's/^v//' | sort -V | tail -n 1) + + if [ -z "$highest_version" ]; then + echo "No existing tags found, this will be latest" + echo "is_latest=true" >> $GITHUB_OUTPUT + else + echo "Current version: $current_version" + echo "Highest existing version: $highest_version" + + # Compare versions using sort -V + highest=$(printf "%s\n%s" "$current_version" "$highest_version" | sort -V | tail -n 1) + + if [ "$highest" = "$current_version" ]; then + echo "This version is higher than or equal to existing versions, marking as latest" + echo "is_latest=true" >> $GITHUB_OUTPUT + else + echo "This version is lower than existing versions, not marking as latest" + echo "is_latest=false" >> $GITHUB_OUTPUT + fi + fi + + - name: Create and push tag + uses: ./.github/actions/create-tag + with: + tag: ${{ steps.extract_version.outputs.tag }} + + create-release: + name: Create GitHub Release + needs: [ create-tag ] + runs-on: ubuntu-latest + + permissions: + contents: write + + steps: + - name: Create GitHub Release + uses: ncipollo/release-action@v1 + with: + tag: ${{ needs.create-tag.outputs.tag }} + name: Release ${{ needs.create-tag.outputs.tag }} + generateReleaseNotes: true + makeLatest: ${{ needs.create-tag.outputs.is_latest == 'true' }} + body: | + NuGet packages published to GitHub Packages. + + ### Installation + ```bash + dotnet add package DataPlane.Sdk.Core --version ${{ needs.create-tag.outputs.version }} + dotnet add package DataPlane.Sdk.Api --version ${{ needs.create-tag.outputs.version }} + ``` + draft: false + prerelease: false From 5e01957f8d444c65e208d9c3f47141c49e067edb Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Tue, 14 Oct 2025 09:26:36 +0200 Subject: [PATCH 2/5] fix release body --- .github/workflows/release_bugfix.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release_bugfix.yml b/.github/workflows/release_bugfix.yml index f065658..fc7a317 100644 --- a/.github/workflows/release_bugfix.yml +++ b/.github/workflows/release_bugfix.yml @@ -99,12 +99,18 @@ jobs: generateReleaseNotes: true makeLatest: ${{ needs.create-tag.outputs.is_latest == 'true' }} body: | - NuGet packages published to GitHub Packages. - - ### Installation + ## Installation + + To use this version in your Go project, run: + ```bash - dotnet add package DataPlane.Sdk.Core --version ${{ needs.create-tag.outputs.version }} - dotnet add package DataPlane.Sdk.Api --version ${{ needs.create-tag.outputs.version }} + go get github.com/${{ github.repository }}@${{ needs.create-tag.outputs.tag }} + ``` + + Or add it to your `go.mod`: + + ```go + require github.com/${{ github.repository }} ${{ needs.create-tag.outputs.tag }} ``` draft: false prerelease: false From f634f13702ae0b943749c0a542f0f5785c049d06 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Tue, 14 Oct 2025 09:28:50 +0200 Subject: [PATCH 3/5] extract GH release action --- .github/actions/create-release/action.yml | 39 +++++++++++++++++++++++ .github/workflows/release.yml | 27 ++++------------ .github/workflows/release_bugfix.yml | 23 ++----------- 3 files changed, 49 insertions(+), 40 deletions(-) create mode 100644 .github/actions/create-release/action.yml diff --git a/.github/actions/create-release/action.yml b/.github/actions/create-release/action.yml new file mode 100644 index 0000000..1be9d55 --- /dev/null +++ b/.github/actions/create-release/action.yml @@ -0,0 +1,39 @@ +name: 'Create GitHub Release' +description: 'Creates a GitHub release with installation instructions' + +inputs: + tag: + description: 'The git tag for the release' + required: true + version: + description: 'The version number' + required: true + repository: + description: 'The GitHub repository (owner/name)' + required: true + +runs: + using: 'composite' + steps: + - name: Create Release + uses: ncipollo/release-action@v1 + with: + tag: ${{ inputs.tag }} + name: Release ${{ inputs.version }} + body: | + ## Installation + + To use this version in your Go project, run: + + ```bash + go get github.com/${{ inputs.repository }}@${{ inputs.tag }} + ``` + + Or add it to your `go.mod`: + + ```go + require github.com/${{ inputs.repository }} ${{ inputs.tag }} + ``` + generateReleaseNotes: true + draft: false + prerelease: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index adee473..f47fd0d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,25 +46,12 @@ jobs: contents: write steps: - - name: Create Release - uses: ncipollo/release-action@v1 + - name: Checkout code + uses: actions/checkout@v4 + + - name: Create GitHub Release + uses: ./.github/actions/create-release with: tag: ${{ needs.create-tag.outputs.tag }} - name: Release ${{ needs.create-tag.outputs.version }} - body: | - ## Installation - - To use this version in your Go project, run: - - ```bash - go get github.com/${{ github.repository }}@${{ needs.create-tag.outputs.tag }} - ``` - - Or add it to your `go.mod`: - - ```go - require github.com/${{ github.repository }} ${{ needs.create-tag.outputs.tag }} - ``` - generateReleaseNotes: true - draft: false - prerelease: false \ No newline at end of file + version: ${{ needs.create-tag.outputs.version }} + repository: ${{ github.repository }} \ No newline at end of file diff --git a/.github/workflows/release_bugfix.yml b/.github/workflows/release_bugfix.yml index fc7a317..e882e98 100644 --- a/.github/workflows/release_bugfix.yml +++ b/.github/workflows/release_bugfix.yml @@ -92,25 +92,8 @@ jobs: steps: - name: Create GitHub Release - uses: ncipollo/release-action@v1 + uses: ./.github/actions/create-release with: tag: ${{ needs.create-tag.outputs.tag }} - name: Release ${{ needs.create-tag.outputs.tag }} - generateReleaseNotes: true - makeLatest: ${{ needs.create-tag.outputs.is_latest == 'true' }} - body: | - ## Installation - - To use this version in your Go project, run: - - ```bash - go get github.com/${{ github.repository }}@${{ needs.create-tag.outputs.tag }} - ``` - - Or add it to your `go.mod`: - - ```go - require github.com/${{ github.repository }} ${{ needs.create-tag.outputs.tag }} - ``` - draft: false - prerelease: false + version: ${{ needs.create-tag.outputs.version }} + repository: ${{ github.repository }} From 9481b281f2f14358074bafed4bcaf514faa5f434 Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Tue, 14 Oct 2025 09:59:04 +0200 Subject: [PATCH 4/5] build: run all samples on CI runs --- .github/workflows/ci_pipeline.yml | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/.github/workflows/ci_pipeline.yml b/.github/workflows/ci_pipeline.yml index ca804e6..7e131e2 100644 --- a/.github/workflows/ci_pipeline.yml +++ b/.github/workflows/ci_pipeline.yml @@ -38,3 +38,36 @@ jobs: run: | go generate ./... go test ./pkg/... ./internal/... --tags=postgres + + verify-examples: + name: Run all examples and verify they succeed + runs-on: ubuntu-latest + strategy: + matrix: + example: + - sync-pull-dataplane + - streaming-pull-dataplane + - streaming-push-dataplane + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + + - name: Go env + run: | + go env + go version + + - name: Run example + working-directory: examples/${{ matrix.example }} + run: | + go build . + go run . + + + \ No newline at end of file From 75139af639e1a6cde97f8ed5f380b00512a35a6e Mon Sep 17 00:00:00 2001 From: Paul Latzelsperger Date: Tue, 14 Oct 2025 10:08:38 +0200 Subject: [PATCH 5/5] rename job --- .github/workflows/ci_pipeline.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci_pipeline.yml b/.github/workflows/ci_pipeline.yml index 7e131e2..09abbac 100644 --- a/.github/workflows/ci_pipeline.yml +++ b/.github/workflows/ci_pipeline.yml @@ -40,7 +40,7 @@ jobs: go test ./pkg/... ./internal/... --tags=postgres verify-examples: - name: Run all examples and verify they succeed + name: Run example ${{ matrix.example }} runs-on: ubuntu-latest strategy: matrix: @@ -70,4 +70,3 @@ jobs: go run . - \ No newline at end of file