diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..d7154f35 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + allow: + - dependency-name: "@shotstack/schemas" + - dependency-name: "@shotstack/shotstack-canvas" + commit-message: + prefix: "chore" + include: "scope" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 320388a0..4d6f8e6d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,8 +1,5 @@ name: CI - on: - push: - branches: [main] pull_request: branches: [main] @@ -20,6 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 with: + fetch-depth: 0 path: shotstack-studio-sdk - uses: actions/setup-node@v4 @@ -30,7 +28,7 @@ jobs: working-directory: shotstack-studio-sdk run: npm install - - name: Run public verification suite + - name: Run verification suite working-directory: shotstack-studio-sdk run: npm run verify:ci @@ -42,7 +40,6 @@ jobs: path: shotstack-studio-sdk/coverage/ retention-days: 14 - # ── Extended regression suite (skipped on forks) ───────────── - name: "[Extended] Set up SSH for regression suite" if: env.HAS_EXTENDED_TESTS == 'true' uses: webfactory/ssh-agent@v0.9.0 @@ -62,3 +59,9 @@ jobs: if: env.HAS_EXTENDED_TESTS == 'true' working-directory: shotstack-studio-extended-regression-suite run: npm test + + - name: Dry run release + working-directory: shotstack-studio-sdk + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: npx semantic-release --dry-run diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..c09c5c68 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,73 @@ +name: Release +on: + push: + branches: [main] + +permissions: + contents: read + +jobs: + release: + name: Verify & Release + runs-on: ubuntu-latest + + permissions: + contents: write + issues: write + pull-requests: write + id-token: write + + env: + HAS_EXTENDED_TESTS: ${{ secrets.EXTENDED_REGRESSION_SSH_KEY != '' }} + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + path: shotstack-studio-sdk + + - uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Install dependencies + working-directory: shotstack-studio-sdk + run: npm install + + - name: Run verification suite + working-directory: shotstack-studio-sdk + run: npm run verify:ci + + - name: Upload coverage report + if: always() + uses: actions/upload-artifact@v4 + with: + name: coverage-report + path: shotstack-studio-sdk/coverage/ + retention-days: 14 + + - name: "[Extended] Set up SSH for regression suite" + if: env.HAS_EXTENDED_TESTS == 'true' + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ secrets.EXTENDED_REGRESSION_SSH_KEY }} + + - name: "[Extended] Clone regression suite" + if: env.HAS_EXTENDED_TESTS == 'true' + run: git clone git@github.com:shotstack/shotstack-studio-extended-regression-suite.git + + - name: "[Extended] Install test dependencies" + if: env.HAS_EXTENDED_TESTS == 'true' + working-directory: shotstack-studio-extended-regression-suite + run: npm install + + - name: "[Extended] Run behavioural regression tests" + if: env.HAS_EXTENDED_TESTS == 'true' + working-directory: shotstack-studio-extended-regression-suite + run: npm test + + - name: Release + working-directory: shotstack-studio-sdk + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: npx semantic-release diff --git a/.npmrc b/.npmrc index 9cf94950..43c97e71 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1 @@ -package-lock=false \ No newline at end of file +package-lock=false diff --git a/.releaserc.json b/.releaserc.json new file mode 100644 index 00000000..fb91eaa0 --- /dev/null +++ b/.releaserc.json @@ -0,0 +1,16 @@ +{ + "branches": ["main"], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/changelog", + ["@semantic-release/npm", { + "pkgRoot": "." + }], + ["@semantic-release/git", { + "assets": ["package.json", "CHANGELOG.md"], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + }], + "@semantic-release/github" + ] +} diff --git a/package.json b/package.json index a57c5364..a50dec0b 100644 --- a/package.json +++ b/package.json @@ -65,10 +65,16 @@ "format": "prettier --ignore-path .gitignore --write .", "verify:ci": "npm run lint && npm run typecheck && npm run test:coverage && npm run build && npm run test:package", "release:check": "npm run verify:ci && npm run test:extended && npm pack --dry-run --json", - "prepublishOnly": "npm run release:check", + "prepublishOnly": "node scripts/publish-guard.cjs", "generate:fonts": "npx tsx scripts/fetch-google-fonts.ts" }, "devDependencies": { + "@semantic-release/changelog": "^6.0.3", + "@semantic-release/commit-analyzer": "^13.0.1", + "@semantic-release/git": "^10.0.1", + "@semantic-release/github": "^12.0.6", + "@semantic-release/npm": "^13.1.5", + "@semantic-release/release-notes-generator": "^14.1.0", "@types/howler": "^2.2.12", "@types/jest": "^30.0.0", "@types/node": "^22.9.0", @@ -83,6 +89,7 @@ "jest": "^30.2.0", "jest-environment-jsdom": "^30.2.0", "prettier": "^3.6.2", + "semantic-release": "^25.0.3", "ts-jest": "^29.4.5", "typescript": "^5.6.2", "vite": "^5.4.10", @@ -97,5 +104,9 @@ "pixi-filters": "^6.0.5", "pixi.js": "^8.15.0", "zod": "^4.0.0" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" } } diff --git a/scripts/publish-guard.cjs b/scripts/publish-guard.cjs new file mode 100644 index 00000000..f783e9e2 --- /dev/null +++ b/scripts/publish-guard.cjs @@ -0,0 +1,11 @@ +if (!process.env.CI) { + console.error( + "\n" + + "========================================\n" + + " Do not run npm/pnpm publish locally.\n" + + " Releases are managed by CI pipeline.\n" + + " Push to main to trigger a release.\n" + + "========================================\n" + ); + process.exit(1); +}