diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml new file mode 100644 index 0000000..f01b194 --- /dev/null +++ b/.forgejo/workflows/release.yml @@ -0,0 +1,87 @@ +name: release + +on: + push: + tags: + - "*" + +permissions: + contents: write + +jobs: + release: + runs-on: codeberg-medium + container: + image: node:22-bookworm + steps: + - uses: https://data.forgejo.org/actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Verify tag is on main + run: | + set -euo pipefail + git fetch origin main + tag_commit="$(git rev-list -n 1 "$GITHUB_REF_NAME")" + git merge-base --is-ancestor "$tag_commit" origin/main + + - name: Install release tools + run: | + apt-get update + apt-get install -y --no-install-recommends ca-certificates curl zip + + - run: npm ci + - run: npm run build + + - name: Zip dist + run: zip -r "diff-highlighter-${GITHUB_REF_NAME}.zip" dist + + - name: Generate release notes + env: + API_URL: ${{ github.server_url }}/api/v1 + REPOSITORY: ${{ github.repository }} + TAG_NAME: ${{ github.ref_name }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + + curl --fail-with-body -sS \ + -H "Authorization: token ${TOKEN}" \ + "${API_URL}/repos/${REPOSITORY}/releases?limit=1" \ + -o releases.json + + previous_tag="$(node -e "const fs = require('fs'); const releases = JSON.parse(fs.readFileSync('releases.json', 'utf8')); console.log(releases[0]?.tag_name ?? '')")" + + if [ -n "${previous_tag}" ] && git rev-parse --verify --quiet "${previous_tag}^{commit}" >/dev/null; then + git log --format='- %s' -n 20 "${previous_tag}..${TAG_NAME}" > release-notes.md + else + git log --format='- %s' -n 20 "${TAG_NAME}" > release-notes.md + fi + + - name: Create Forgejo release + env: + API_URL: ${{ github.server_url }}/api/v1 + REPOSITORY: ${{ github.repository }} + TAG_NAME: ${{ github.ref_name }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + asset="diff-highlighter-${TAG_NAME}.zip" + + node -e "const fs = require('fs'); const payload = { tag_name: process.env.TAG_NAME, name: process.env.TAG_NAME, body: fs.readFileSync('release-notes.md', 'utf8').trim() }; fs.writeFileSync('release.json.payload', JSON.stringify(payload));" + + curl --fail-with-body -sS \ + -H "Authorization: token ${TOKEN}" \ + -H "Content-Type: application/json" \ + -X POST \ + -d @release.json.payload \ + "${API_URL}/repos/${REPOSITORY}/releases" \ + -o release.json + + release_id="$(node -e "const fs = require('fs'); console.log(JSON.parse(fs.readFileSync('release.json', 'utf8')).id)")" + + curl --fail-with-body -sS \ + -H "Authorization: token ${TOKEN}" \ + -X POST \ + -F "attachment=@${asset}" \ + "${API_URL}/repos/${REPOSITORY}/releases/${release_id}/assets?name=${asset}"