From 0ec8096b0bb114efdb5b2978ec2688a799ec2de3 Mon Sep 17 00:00:00 2001 From: cooronx <2197083441@qq.com> Date: Tue, 28 Apr 2026 21:05:42 +0800 Subject: [PATCH] feat: auto release snapshot version now --- .github/workflows/main.yml | 103 ++++++++++++++++++++-- .github/workflows/npm-snapshot.yml | 50 +++++++++++ .github/workflows/semantic-relese.yml | 121 ++++++++++++++++++++++++++ 3 files changed, 267 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/npm-snapshot.yml create mode 100644 .github/workflows/semantic-relese.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 95a1217..8c6a663 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,15 +28,104 @@ jobs: flags: node-${{ matrix.node-version }} fail_ci_if_error: false - semantic-release: + prepare_snapshot_version: + name: Prepare Snapshot Version needs: [test] + if: >- + ${{ + github.repository == 'apache/casbin-node-casbin' && + github.event_name == 'push' && + github.ref == 'refs/heads/master' + }} runs-on: ubuntu-latest + outputs: + version: ${{ steps.snapshot.outputs.version }} + npm_version: ${{ steps.snapshot.outputs.npm_version }} + basename: ${{ steps.snapshot.outputs.basename }} + previous_tag: ${{ steps.snapshot.outputs.previous_tag }} steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.sha }} + + - name: Compute snapshot version + id: snapshot + run: | + LATEST_RELEASE_TAG="$( + git tag --list 'v*' | + grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | + sort -V | + tail -n 1 + )" + + if [ -z "${LATEST_RELEASE_TAG}" ]; then + BASE_VERSION="0.1.0" + else + RELEASE_VERSION="${LATEST_RELEASE_TAG#v}" + MAJOR="${RELEASE_VERSION%%.*}" + REST="${RELEASE_VERSION#*.}" + MINOR="${REST%%.*}" + NEXT_MINOR="$((MINOR + 1))" + BASE_VERSION="${MAJOR}.${NEXT_MINOR}.0" + fi + + ESCAPED_BASE_VERSION="${BASE_VERSION//./\\.}" + LAST_SNAPSHOT_NUMBER="$( + git tag --list "v${BASE_VERSION}-snapshot.*" | + sed -nE "s/^v${ESCAPED_BASE_VERSION}-snapshot\.([0-9]+)$/\1/p" | + sort -n | + tail -n 1 + )" + LAST_SNAPSHOT_NUMBER="${LAST_SNAPSHOT_NUMBER:-0}" + NEXT_SNAPSHOT_NUMBER="$((LAST_SNAPSHOT_NUMBER + 1))" + SNAPSHOT_VERSION="v${BASE_VERSION}-snapshot.${NEXT_SNAPSHOT_NUMBER}" + NPM_VERSION="${SNAPSHOT_VERSION#v}" + BASENAME="casbin-${NPM_VERSION}-src" + + echo "version=${SNAPSHOT_VERSION}" >> "${GITHUB_OUTPUT}" + echo "npm_version=${NPM_VERSION}" >> "${GITHUB_OUTPUT}" + echo "basename=${BASENAME}" >> "${GITHUB_OUTPUT}" + if [ "${LAST_SNAPSHOT_NUMBER}" -gt 0 ]; then + echo "previous_tag=v${BASE_VERSION}-snapshot.${LAST_SNAPSHOT_NUMBER}" >> "${GITHUB_OUTPUT}" + else + echo "previous_tag=${LATEST_RELEASE_TAG}" >> "${GITHUB_OUTPUT}" + fi + + echo "Computed snapshot version: ${SNAPSHOT_VERSION}" + echo "Computed npm version: ${NPM_VERSION}" + + publish-npm: + name: Publish NPM + needs: prepare_snapshot_version + if: >- + ${{ + github.repository == 'apache/casbin-node-casbin' && + github.event_name == 'push' && + github.ref == 'refs/heads/master' + }} + uses: ./.github/workflows/npm-snapshot.yml + with: + npm_version: ${{ needs.prepare_snapshot_version.outputs.npm_version }} + ref: ${{ github.sha }} + secrets: inherit - - name: Run semantic-release - if: github.repository == 'apache/casbin-node-casbin' && github.event_name == 'push' - run: yarn install && yarn semantic-release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + semantic-relese: + name: semantic-relese + needs: + - prepare_snapshot_version + - publish-npm + if: >- + ${{ + github.repository == 'apache/casbin-node-casbin' && + github.event_name == 'push' && + github.ref == 'refs/heads/master' + }} + permissions: + contents: write + uses: ./.github/workflows/semantic-relese.yml + with: + version: ${{ needs.prepare_snapshot_version.outputs.version }} + basename: ${{ needs.prepare_snapshot_version.outputs.basename }} + previous_tag: ${{ needs.prepare_snapshot_version.outputs.previous_tag }} + ref: ${{ github.sha }} diff --git a/.github/workflows/npm-snapshot.yml b/.github/workflows/npm-snapshot.yml new file mode 100644 index 0000000..71e5f5a --- /dev/null +++ b/.github/workflows/npm-snapshot.yml @@ -0,0 +1,50 @@ +name: Publish NPM + +on: + workflow_call: + inputs: + npm_version: + required: true + type: string + ref: + required: true + type: string + workflow_dispatch: + inputs: + npm_version: + description: NPM snapshot version to publish, for example 1.2.3-snapshot.1 + required: true + type: string + ref: + description: Git ref or commit SHA to publish + required: true + type: string + +permissions: + contents: read + +jobs: + publish-npm: + name: Publish NPM + if: ${{ github.repository == 'apache/casbin-node-casbin' }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref }} + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + registry-url: https://registry.npmjs.org + + - name: Publish snapshot package + run: | + yarn install --frozen-lockfile + npm version "${{ inputs.npm_version }}" --no-git-tag-version + npm publish --tag snapshot + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/semantic-relese.yml b/.github/workflows/semantic-relese.yml new file mode 100644 index 0000000..deafbdc --- /dev/null +++ b/.github/workflows/semantic-relese.yml @@ -0,0 +1,121 @@ +name: semantic-relese + +on: + workflow_call: + inputs: + version: + required: true + type: string + basename: + required: true + type: string + previous_tag: + required: false + type: string + default: "" + ref: + required: true + type: string + workflow_dispatch: + inputs: + version: + description: GitHub release tag, for example v1.2.3-snapshot.1 + required: true + type: string + basename: + description: Source archive basename, for example casbin-1.2.3-snapshot.1-src + required: true + type: string + previous_tag: + description: Previous tag for release notes + required: false + type: string + ref: + description: Git ref or commit SHA for the snapshot + required: true + type: string + +permissions: + contents: write + +jobs: + semantic-relese: + name: semantic-relese + if: ${{ github.repository == 'apache/casbin-node-casbin' }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref }} + + - name: Generate snapshot release notes + run: | + PREVIOUS_TAG="${{ inputs.previous_tag }}" + CURRENT_TAG="${{ inputs.version }}" + CURRENT_VERSION="${CURRENT_TAG#v}" + RELEASE_DATE="$(date -u +%F)" + RANGE="HEAD" + + if [ -n "${PREVIOUS_TAG}" ]; then + RANGE="${PREVIOUS_TAG}..HEAD" + fi + + FEATURES="$(git log --pretty=format:'%s (%h)' "${RANGE}" | grep -Ei '^(feat)(\(.+\))?: ' || true)" + FIXES="$(git log --pretty=format:'%s (%h)' "${RANGE}" | grep -Ei '^(fix)(\(.+\))?: ' || true)" + DOCS="$(git log --pretty=format:'%s (%h)' "${RANGE}" | grep -Ei '^(docs?|doc)(\(.+\))?: ' || true)" + + { + if [ -n "${PREVIOUS_TAG}" ]; then + echo "# [${CURRENT_VERSION}](https://github.com/${GITHUB_REPOSITORY}/compare/${PREVIOUS_TAG}...${CURRENT_TAG}) (${RELEASE_DATE})" + else + echo "# ${CURRENT_VERSION} (${RELEASE_DATE})" + fi + echo + if [ -n "${FEATURES}" ]; then + echo "## Features" + echo + printf '%s\n' "${FEATURES}" | sed 's/^/- /' + echo + fi + + if [ -n "${FIXES}" ]; then + echo "## Fixes" + echo + printf '%s\n' "${FIXES}" | sed 's/^/- /' + echo + fi + + if [ -n "${DOCS}" ]; then + echo "## Docs" + echo + printf '%s\n' "${DOCS}" | sed 's/^/- /' + echo + fi + + if [ -z "${FEATURES}${FIXES}${DOCS}" ]; then + echo "## Notes" + echo + echo "- No feat/fix/doc commits were found in this snapshot range." + fi + } > SNAPSHOT_RELEASE_NOTES.md + + - name: Create source archives + run: | + mkdir -p dist + git archive --format=tar.gz --prefix="${{ inputs.basename }}/" -o "dist/${{ inputs.basename }}.tar.gz" HEAD + git archive --format=zip --prefix="${{ inputs.basename }}/" -o "dist/${{ inputs.basename }}.zip" HEAD + + - name: Create source snapshot release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ inputs.version }} + target_commitish: ${{ inputs.ref }} + name: ${{ inputs.version }} + body_path: SNAPSHOT_RELEASE_NOTES.md + draft: false + prerelease: false + files: | + dist/${{ inputs.basename }}.tar.gz + dist/${{ inputs.basename }}.zip