From 08a2a4f4764e2e3ca5300458896224de740d289f Mon Sep 17 00:00:00 2001 From: Szymon Wlodarski Date: Mon, 8 Dec 2025 10:24:12 +0100 Subject: [PATCH 1/3] #406 Add GitHub Actions workflow for automated release process --- .github/workflows/release.yml | 158 ++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..c5db0eae --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,158 @@ +name: Release + +on: + workflow_dispatch: + inputs: + branch: + description: "Branch to release from" + required: true + default: "master" + type: string + version: + description: "Version number (e.g., 9.3.3)" + required: true + type: string + overview: + description: "Release overview (will be placed at top of notes)" + required: true + type: string + +jobs: + release: + name: Create tag and release + runs-on: ubuntu-latest + outputs: + version: ${{ steps.version.outputs.version }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ inputs.branch }} + fetch-depth: 0 + + - name: Validate version format + id: version + run: | + if [[ ! "${{ inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: Version must be in format X.Y.Z (e.g., 9.3.3)" + exit 1 + fi + version="${{ inputs.version }}" + echo "version=$version" >> $GITHUB_OUTPUT + + - name: Configure Git + run: | + git config user.name "github-actions" + git config user.email "github-actions@github.com" + + - name: Update Env.php version + run: | + VERSION="${{ steps.version.outputs.version }}" + sed -i "s/public const BITPAY_PLUGIN_INFO = \"BitPay_PHP_Client_v[0-9.]*\";/public const BITPAY_PLUGIN_INFO = \"BitPay_PHP_Client_v${VERSION}\";/" src/BitPaySDK/Env.php + echo "Updated Env.php with version ${VERSION}" + cat src/BitPaySDK/Env.php | grep BITPAY_PLUGIN_INFO + + - name: Update phpdoc.dist.xml version + run: | + VERSION="${{ steps.version.outputs.version }}" + sed -i "s///" phpdoc.dist.xml + echo "Updated phpdoc.dist.xml with version ${VERSION}" + cat phpdoc.dist.xml | grep -A 1 "> $GITHUB_ENV + echo "${{ github.event.inputs.overview }}" >> $GITHUB_ENV + echo "" >> $GITHUB_ENV + echo "## What's Changed" >> $GITHUB_ENV + echo "$joined" >> $GITHUB_ENV + echo "" >> $GITHUB_ENV + echo "$changelog" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Create GitHub Release + run: | + gh release create "${{ steps.version.outputs.version }}" \ + --title "${{ steps.version.outputs.version }}" \ + --notes "${{ env.RELEASE_NOTES }}" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + readme-changelog: + name: Publish changelog to Readme + needs: release + runs-on: ubuntu-latest + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Extract release data + id: release_data + run: | + echo "title=${{ needs.release.outputs.version }}" >> $GITHUB_OUTPUT + body=$(gh release view ${{ needs.release.outputs.version }} --json body --jq .body) + body_escaped=$(echo "$body" \ + | sed 's/&/\&/g' \ + | sed 's//\>/g' \ + | sed 's/{/\{/g' \ + | sed 's/}/\}/g') + { + echo "body<> $GITHUB_OUTPUT + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish changelog to Readme + env: + README_API_KEY: ${{ secrets.README_API_KEY }} + run: | + jq -n --arg title "BitPay PHP SDK v${{ steps.release_data.outputs.title }}" \ + --arg body "${{ steps.release_data.outputs.body }}" \ + '{ + title: $title, + content: { + body: $body + }, + privacy: { view: "public" } + }' > payload.json + + curl --location 'https://api.readme.com/v2/changelogs' \ + --header "Authorization: Bearer $README_API_KEY" \ + --header 'Content-Type: application/json' \ + --data @payload.json From ee35a10b9800ed3761f823237e7155e1bf8aca29 Mon Sep 17 00:00:00 2001 From: Szymon Wlodarski Date: Mon, 8 Dec 2025 12:15:22 +0100 Subject: [PATCH 2/3] #406 Update checkout image version --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c5db0eae..d00b2262 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: ref: ${{ inputs.branch }} fetch-depth: 0 @@ -117,7 +117,7 @@ jobs: steps: - name: Checkout repo - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Extract release data id: release_data From ada0310520a0aafbb90962f76c77a64e2ba06925 Mon Sep 17 00:00:00 2001 From: Szymon Wlodarski Date: Mon, 2 Feb 2026 10:16:11 +0100 Subject: [PATCH 3/3] #406 Security: Fix untrusted input vulnerability in release workflow --- .github/workflows/release.yml | 64 ++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d00b2262..c4130787 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,13 +33,14 @@ jobs: - name: Validate version format id: version + env: + VERSION_INPUT: ${{ inputs.version }} run: | - if [[ ! "${{ inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + if [[ ! "$VERSION_INPUT" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "Error: Version must be in format X.Y.Z (e.g., 9.3.3)" exit 1 fi - version="${{ inputs.version }}" - echo "version=$version" >> $GITHUB_OUTPUT + echo "version=$VERSION_INPUT" >> $GITHUB_OUTPUT - name: Configure Git run: | @@ -47,32 +48,44 @@ jobs: git config user.email "github-actions@github.com" - name: Update Env.php version + env: + VERSION: ${{ steps.version.outputs.version }} run: | - VERSION="${{ steps.version.outputs.version }}" sed -i "s/public const BITPAY_PLUGIN_INFO = \"BitPay_PHP_Client_v[0-9.]*\";/public const BITPAY_PLUGIN_INFO = \"BitPay_PHP_Client_v${VERSION}\";/" src/BitPaySDK/Env.php echo "Updated Env.php with version ${VERSION}" cat src/BitPaySDK/Env.php | grep BITPAY_PLUGIN_INFO - name: Update phpdoc.dist.xml version + env: + VERSION: ${{ steps.version.outputs.version }} run: | - VERSION="${{ steps.version.outputs.version }}" sed -i "s///" phpdoc.dist.xml echo "Updated phpdoc.dist.xml with version ${VERSION}" cat phpdoc.dist.xml | grep -A 1 "> $GITHUB_ENV - echo "${{ github.event.inputs.overview }}" >> $GITHUB_ENV + echo "$OVERVIEW" >> $GITHUB_ENV echo "" >> $GITHUB_ENV echo "## What's Changed" >> $GITHUB_ENV echo "$joined" >> $GITHUB_ENV echo "" >> $GITHUB_ENV echo "$changelog" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Create GitHub Release - run: | - gh release create "${{ steps.version.outputs.version }}" \ - --title "${{ steps.version.outputs.version }}" \ - --notes "${{ env.RELEASE_NOTES }}" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NOTES: ${{ env.RELEASE_NOTES }} + VERSION: ${{ steps.version.outputs.version }} + run: | + gh release create "$VERSION" \ + --title "$VERSION" \ + --notes "$NOTES" readme-changelog: name: Publish changelog to Readme @@ -121,9 +134,12 @@ jobs: - name: Extract release data id: release_data + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + VERSION: ${{ needs.release.outputs.version }} run: | - echo "title=${{ needs.release.outputs.version }}" >> $GITHUB_OUTPUT - body=$(gh release view ${{ needs.release.outputs.version }} --json body --jq .body) + echo "title=$VERSION" >> $GITHUB_OUTPUT + body=$(gh release view "$VERSION" --json body --jq .body) body_escaped=$(echo "$body" \ | sed 's/&/\&/g' \ | sed 's/> $GITHUB_OUTPUT - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Publish changelog to Readme env: README_API_KEY: ${{ secrets.README_API_KEY }} + RELEASE_TITLE: ${{ steps.release_data.outputs.title }} + RELEASE_BODY: ${{ steps.release_data.outputs.body }} run: | - jq -n --arg title "BitPay PHP SDK v${{ steps.release_data.outputs.title }}" \ - --arg body "${{ steps.release_data.outputs.body }}" \ + jq -n --arg title "BitPay PHP SDK v$RELEASE_TITLE" \ + --arg body "$RELEASE_BODY" \ '{ title: $title, content: {