Expose API error metadata (#49) #8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy on main when version increases | |
| on: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| deploy: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Decide release version | |
| id: version | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [[ ! -f VERSION.md ]]; then | |
| echo "Missing VERSION.md file" | |
| exit 1 | |
| fi | |
| LOCAL_VERSION="$(head -n1 VERSION.md | tr -d '[:space:]')" | |
| RELEASE_BODY="$(tail -n +2 VERSION.md || true)" | |
| if [[ ! "$LOCAL_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then | |
| echo "VERSION.md first line must be valid semver. Got: $LOCAL_VERSION" | |
| exit 1 | |
| fi | |
| git fetch --tags origin | |
| REMOTE_MAX="$(git ls-remote --tags --refs origin \ | |
| | awk '{print $2}' \ | |
| | sed 's#refs/tags/##' \ | |
| | sed 's/^v//' \ | |
| | grep -E '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$' \ | |
| | sort -V \ | |
| | tail -n1 || true)" | |
| if [[ -z "$REMOTE_MAX" ]]; then | |
| REMOTE_MAX="0.0.0" | |
| fi | |
| echo "Local version: $LOCAL_VERSION" | |
| echo "Remote version: $REMOTE_MAX" | |
| if [[ "$LOCAL_VERSION" == "$REMOTE_MAX" ]]; then | |
| echo "should_deploy=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| HIGHEST="$(printf '%s\n%s\n' "$REMOTE_MAX" "$LOCAL_VERSION" | sort -V | tail -n1)" | |
| if [[ "$HIGHEST" != "$LOCAL_VERSION" ]]; then | |
| echo "Local VERSION.md is not greater than remote max tag" | |
| echo "should_deploy=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if ! printf '%s' "$RELEASE_BODY" | grep -q '[^[:space:]]'; then | |
| echo "VERSION.md requires release notes after the first line when publishing." | |
| echo "Example:" | |
| echo " 3.6.1" | |
| echo " ## What changed" | |
| echo " - Added X" | |
| exit 1 | |
| fi | |
| printf '%s\n' "$RELEASE_BODY" > RELEASE_NOTES.md | |
| echo "should_deploy=true" >> "$GITHUB_OUTPUT" | |
| echo "tag=$LOCAL_VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Create and push tag | |
| if: steps.version.outputs.should_deploy == 'true' | |
| run: | | |
| set -euo pipefail | |
| TAG="${{ steps.version.outputs.tag }}" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "Tag already exists locally: $TAG" | |
| exit 0 | |
| fi | |
| git tag "$TAG" | |
| git push origin "$TAG" | |
| - name: Create GitHub release | |
| id: release | |
| if: steps.version.outputs.should_deploy == 'true' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.version.outputs.tag }} | |
| name: ${{ steps.version.outputs.tag }} | |
| body_path: RELEASE_NOTES.md | |
| - name: Notify Slack (success) | |
| if: steps.version.outputs.should_deploy == 'true' && steps.release.outcome == 'success' | |
| env: | |
| SLACK_DEPLOY_WEBHOOK_URL: ${{ secrets.SLACK_DEPLOY_WEBHOOK_URL }} | |
| VERSION: ${{ steps.version.outputs.tag }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${SLACK_DEPLOY_WEBHOOK_URL:-}" ]; then | |
| echo "SLACK_DEPLOY_WEBHOOK_URL not set; skipping Slack notification" | |
| exit 0 | |
| fi | |
| node <<'JS' | |
| const fs = require('node:fs'); | |
| const version = process.env.VERSION; | |
| const releaseNotes = fs.existsSync('RELEASE_NOTES.md') | |
| ? fs.readFileSync('RELEASE_NOTES.md', 'utf8').trim() | |
| : 'See release notes for details.'; | |
| fs.writeFileSync('/tmp/slack_payload.json', JSON.stringify({ | |
| text: `Facturapi PHP SDK ${version} released`, | |
| blocks: [ | |
| { | |
| type: 'header', | |
| text: { | |
| type: 'plain_text', | |
| text: `PHP SDK ${version} released`, | |
| }, | |
| }, | |
| { | |
| type: 'section', | |
| fields: [ | |
| { type: 'mrkdwn', text: `*Package:* \`facturapi/facturapi-php:${version}\`` }, | |
| { type: 'mrkdwn', text: `*Branch:* \`${process.env.GITHUB_REF_NAME}\`` }, | |
| { type: 'mrkdwn', text: `*Commit:* \`${process.env.GITHUB_SHA}\`` }, | |
| { type: 'mrkdwn', text: `*Actor:* \`${process.env.GITHUB_ACTOR}\`` }, | |
| ], | |
| }, | |
| { | |
| type: 'section', | |
| text: { | |
| type: 'mrkdwn', | |
| text: [ | |
| '*Useful links*', | |
| `• Packagist: <https://packagist.org/packages/facturapi/facturapi-php#${version}|View package>`, | |
| `• GitHub release: <${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/releases/tag/${version}|Open release>`, | |
| `• Workflow run: <${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}|Open run>`, | |
| ].join('\n'), | |
| }, | |
| }, | |
| { | |
| type: 'section', | |
| text: { | |
| type: 'mrkdwn', | |
| text: `*Latest changes*\n${releaseNotes}`, | |
| }, | |
| }, | |
| ], | |
| })); | |
| JS | |
| curl -sS -X POST -H "Content-type: application/json" --data "@/tmp/slack_payload.json" "$SLACK_DEPLOY_WEBHOOK_URL" || true | |
| - name: Notify Slack (failure) | |
| if: failure() && steps.version.outputs.should_deploy == 'true' | |
| env: | |
| SLACK_DEPLOY_WEBHOOK_URL: ${{ secrets.SLACK_DEPLOY_WEBHOOK_URL }} | |
| VERSION: ${{ steps.version.outputs.tag }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${SLACK_DEPLOY_WEBHOOK_URL:-}" ]; then | |
| echo "SLACK_DEPLOY_WEBHOOK_URL not set; skipping Slack notification" | |
| exit 0 | |
| fi | |
| node <<'JS' | |
| const fs = require('node:fs'); | |
| fs.writeFileSync('/tmp/slack_payload_failure.json', JSON.stringify({ | |
| text: `Facturapi PHP SDK ${process.env.VERSION} release failed`, | |
| blocks: [ | |
| { | |
| type: 'section', | |
| text: { | |
| type: 'mrkdwn', | |
| text: [ | |
| `*PHP SDK ${process.env.VERSION} release failed*`, | |
| `• Workflow run: <${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}|Open run>`, | |
| `• Commit: \`${process.env.GITHUB_SHA}\``, | |
| ].join('\n'), | |
| }, | |
| }, | |
| ], | |
| })); | |
| JS | |
| curl -sS -X POST -H "Content-type: application/json" --data "@/tmp/slack_payload_failure.json" "$SLACK_DEPLOY_WEBHOOK_URL" || true | |
| - name: Deploy skipped | |
| if: steps.version.outputs.should_deploy != 'true' | |
| run: | | |
| echo "Skipping deploy: local VERSION.md is not greater than remote semver tag." |