From 7a3b18d3a188641346a9f04ce47a0822754bfced Mon Sep 17 00:00:00 2001 From: Samuel Salazar Date: Mon, 9 Feb 2026 19:38:42 -0500 Subject: [PATCH] ci: add semantic-release automation --- .commitlintrc.json | 3 ++ .github/workflows/commitlint.yml | 25 +++++++++ .github/workflows/prepare-release.yml | 75 +++++++++++++++++++++++++++ .github/workflows/release.yml | 66 +++++++++++++++++++++++ .github/workflows/sca-scan.yml | 10 ++++ .github/workflows/semgrep.yml | 20 ------- .github/workflows/test.yml | 39 ++++++++++++++ .husky/commit-msg | 1 + .releaserc.json | 22 ++++++++ .travis.yml | 6 --- package.json | 14 +++-- tsconfig.json | 3 +- 12 files changed, 253 insertions(+), 31 deletions(-) create mode 100644 .commitlintrc.json create mode 100644 .github/workflows/commitlint.yml create mode 100644 .github/workflows/prepare-release.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/sca-scan.yml delete mode 100644 .github/workflows/semgrep.yml create mode 100644 .github/workflows/test.yml create mode 100755 .husky/commit-msg create mode 100644 .releaserc.json delete mode 100644 .travis.yml diff --git a/.commitlintrc.json b/.commitlintrc.json new file mode 100644 index 00000000..c30e5a97 --- /dev/null +++ b/.commitlintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["@commitlint/config-conventional"] +} diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 00000000..7e4c1a5e --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,25 @@ +name: Lint Commits + +on: + pull_request: + +jobs: + commitlint: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + with: + node-version: '24' + + - name: Install dependencies + run: npm install + + - name: Validate commit messages + run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml new file mode 100644 index 00000000..5ad59720 --- /dev/null +++ b/.github/workflows/prepare-release.yml @@ -0,0 +1,75 @@ +name: Prepare Release + +on: + push: + branches: + - master + +concurrency: + group: prepare-release + cancel-in-progress: true + +permissions: + contents: write + pull-requests: write + +jobs: + prepare: + runs-on: ubuntu-latest + if: "!startsWith(github.event.head_commit.message, 'chore(release):')" + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + with: + node-version: '24' + + - name: Install dependencies + run: npm install + + - name: Build + run: npm run build + + - name: Detect Next Version + id: version + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Run semantic-release with only commit analyzer to detect version + NEXT_VERSION=$(npx semantic-release --dry-run --plugins @semantic-release/commit-analyzer | tee /dev/stderr | awk '/The next release version is/{print $NF}') + echo "next=$NEXT_VERSION" >> $GITHUB_OUTPUT + + - name: Update package.json + if: steps.version.outputs.next != '' + run: npm version "$NEXT_VERSION" --no-git-tag-version + env: + NEXT_VERSION: ${{ steps.version.outputs.next }} + + - name: Update CHANGELOG.md + if: steps.version.outputs.next != '' + run: npx conventional-changelog-cli -p angular -i CHANGELOG.md -s + + - name: Create Pull Request + if: steps.version.outputs.next != '' + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "chore(release): ${{ steps.version.outputs.next }}" + branch: "release/v${{ steps.version.outputs.next }}" + delete-branch: true + title: "chore(release): ${{ steps.version.outputs.next }}" + body: | + This PR prepares the release of version ${{ steps.version.outputs.next }}. + + **Changes:** + - Updated version in `package.json` to ${{ steps.version.outputs.next }} + - Updated `CHANGELOG.md` with release notes + + **Next Steps:** + Review and merge this PR to trigger the publish workflow. + labels: release diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b66ff37e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,66 @@ +name: Release + +on: + push: + branches: + - master + +permissions: + contents: write + issues: write + pull-requests: write + id-token: write + +jobs: + release: + runs-on: ubuntu-latest + if: startsWith(github.event.head_commit.message, 'chore(release):') + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + with: + node-version: '24' + + - name: Install dependencies + run: npm install + + - name: Build + run: npm run build + + - name: Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 + with: + python-version: "3.10" + + - name: Install Python dependencies + shell: bash + run: pip install boto3>=1.34.159 requests>=2.32.3 rl-deploy>=2.2.3.0 pip-system-certs>=4.0 + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + with: + role-to-assume: ${{ secrets.PRODSEC_TOOLS_ARN }} + aws-region: us-east-1 + mask-aws-account-id: true + + - name: Install rl-wrapper + env: + WRAPPER_INDEX_URL: "https://${{ secrets.PRODSEC_TOOLS_USER }}:${{ secrets.PRODSEC_TOOLS_TOKEN }}@a0us.jfrog.io/artifactory/api/pypi/python-local/simple" + run: pip install "rl-wrapper>=1.0.0" --index-url $WRAPPER_INDEX_URL + + - name: Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_CONFIG_PROVENANCE: true + RLSECURE_LICENSE: ${{ secrets.RLSECURE_LICENSE }} + RLSECURE_SITE_KEY: ${{ secrets.RLSECURE_SITE_KEY }} + SIGNAL_HANDLER_TOKEN: ${{ secrets.SIGNAL_HANDLER_TOKEN }} + PYTHONUNBUFFERED: 1 + run: npx semantic-release diff --git a/.github/workflows/sca-scan.yml b/.github/workflows/sca-scan.yml new file mode 100644 index 00000000..4a61d879 --- /dev/null +++ b/.github/workflows/sca-scan.yml @@ -0,0 +1,10 @@ +name: Snyk Scan + +on: + push: + branches: ["master"] + +jobs: + snyk-cli: + uses: auth0/devsecops-tooling/.github/workflows/sca-scan.yml@5246a8b59100e3eea284ce4f2e2a51b51e237380 + secrets: inherit diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml deleted file mode 100644 index 783582a6..00000000 --- a/.github/workflows/semgrep.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Semgrep - -on: - pull_request_target: {} - push: - branches: ["master", "main"] -permissions: - contents: read -jobs: - semgrep: - name: Scan - runs-on: ubuntu-latest - container: - image: returntocorp/semgrep - if: (github.actor != 'dependabot[bot]' && github.actor != 'snyk-bot') - steps: - - uses: actions/checkout@v3 - - run: semgrep ci - env: - SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..681bd5e4 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,39 @@ +name: Test + +on: + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: ['20', '22', '24'] + + steps: + - name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 + with: + node-version: ${{ matrix.node-version }} + + - name: Install dependencies + run: npm install + + - name: Build + run: npm run build + + - name: Lint + run: npm run lint + + - name: Test + run: npm test diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 00000000..0a4b97de --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1 @@ +npx --no -- commitlint --edit $1 diff --git a/.releaserc.json b/.releaserc.json new file mode 100644 index 00000000..c4ae630a --- /dev/null +++ b/.releaserc.json @@ -0,0 +1,22 @@ +{ + "branches": ["master"], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + [ + "@semantic-release/npm", + { + "npmPublish": true, + "pkgRoot": "." + } + ], + [ + "@semantic-release/exec", + { + "verifyReleaseCmd": "ARTIFACT=\"$(pwd)/$(npm pack --ignore-scripts | tail -1)\" && rl-wrapper --artifact \"$ARTIFACT\" --name express-jwt --version ${nextRelease.version} --repository $GITHUB_REPOSITORY --commit $GITHUB_SHA --build-env github_actions --suppress-output", + "prepareCmd": "git diff --exit-code -- package.json" + } + ], + "@semantic-release/github" + ] +} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 86bcfa44..00000000 --- a/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: "node_js" -before_install: npm i -g npm@2 -node_js: - - 8 - - 10 - - 12 diff --git a/package.json b/package.json index e2d12a3f..2254096e 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ ], "repository": { "type": "git", - "url": "git://github.com/auth0/express-jwt.git" + "url": "https://github.com/auth0/express-jwt.git" }, "bugs": { "url": "http://github.com/auth0/express-jwt/issues" @@ -31,7 +31,7 @@ "types": "dist/index.d.ts", "files": [ "README.md", - "/dist" + "dist" ], "dependencies": { "@types/jsonwebtoken": "^9", @@ -41,13 +41,19 @@ "devDependencies": { "@types/express": "^4.17.16", "@types/mocha": "^9.1.0", + "@types/node": "^18.19.130", "@typescript-eslint/eslint-plugin": "^5.15.0", "@typescript-eslint/parser": "^5.15.0", - "conventional-changelog": "^3.1.25", + "@commitlint/cli": "^20.3.1", + "@commitlint/config-conventional": "^20.3.1", + "@semantic-release/exec": "^7.1.0", + "@semantic-release/git": "^10.0.1", "eslint": "^8.11.0", "express": "^4.17.3", + "husky": "^9.1.7", "mocha": "^10.2.0", "prettier": "^2.6.0", + "semantic-release": "^25.0.2", "ts-node": "^10.7.0", "typescript": "^4.6.2" }, @@ -56,7 +62,7 @@ }, "scripts": { "build": "rm -rf dist ; tsc", - "prepare": "npm run build", + "prepare": "husky", "test": "mocha --reporter spec --require ts-node/register test/**", "lint": "eslint --fix --ext .ts ./src" } diff --git a/tsconfig.json b/tsconfig.json index fdacb5ff..8a368e68 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,8 @@ "allowJs": true, "target": "es5", "declaration": true, - "esModuleInterop": false + "esModuleInterop": false, + "skipLibCheck": true }, "include": [ "./src/**/*"