diff --git a/.github/workflows/check-version-bump.yml b/.github/workflows/check-version-bump.yml new file mode 100644 index 0000000..31bdf66 --- /dev/null +++ b/.github/workflows/check-version-bump.yml @@ -0,0 +1,79 @@ +# Catches when developers forget to bump package.json for release-affecting changes. +# App code changes (app.js, bin/, config/, routes/, views/, etc.) require a version bump vs latest tag. +# Skips for: test-only, docs, .github (workflows/config), dependency-only bumps without app edits. +name: Check Version Bump + +on: + pull_request: + +jobs: + version-bump: + name: Version bump + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Detect changed files and version bump + id: detect + run: | + if git rev-parse HEAD^2 >/dev/null 2>&1; then + FILES=$(git diff --name-only HEAD^1 HEAD^2) + else + FILES=$(git diff --name-only HEAD~1 HEAD) + fi + VERSION_FILES_CHANGED=false + echo "$FILES" | grep -qx 'package.json' && VERSION_FILES_CHANGED=true + echo "version_files_changed=$VERSION_FILES_CHANGED" >> $GITHUB_OUTPUT + # App source paths for this boilerplate (no lib/webpack/dist); .github/ and test/ do not count + CODE_CHANGED=false + echo "$FILES" | grep -qE '^app\.js$|^bin/|^config/|^middlewares/|^models/|^public/|^routes/|^views/|^schemaNentries/' && CODE_CHANGED=true + echo "$FILES" | grep -qx 'package.json' && CODE_CHANGED=true + echo "code_changed=$CODE_CHANGED" >> $GITHUB_OUTPUT + + - name: Skip when only test/docs/.github changed + if: steps.detect.outputs.code_changed != 'true' + run: | + echo "No release-affecting files changed (e.g. only test/docs/.github). Skipping version-bump check." + exit 0 + + - name: Fail when version bump was missed + if: steps.detect.outputs.code_changed == 'true' && steps.detect.outputs.version_files_changed != 'true' + run: | + echo "::error::This PR has code changes but no version bump. Please bump the version in package.json." + exit 1 + + - name: Setup Node + if: steps.detect.outputs.code_changed == 'true' && steps.detect.outputs.version_files_changed == 'true' + uses: actions/setup-node@v4 + with: + node-version: '22.x' + + - name: Check version bump + if: steps.detect.outputs.code_changed == 'true' && steps.detect.outputs.version_files_changed == 'true' + run: | + set -e + PKG_VERSION=$(node -p "require('./package.json').version.replace(/^v/, '')") + if [ -z "$PKG_VERSION" ]; then + echo "::error::Could not read version from package.json" + exit 1 + fi + git fetch --tags --force 2>/dev/null || true + LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || true) + if [ -z "$LATEST_TAG" ]; then + echo "No existing tags found. Skipping version-bump check (first release)." + exit 0 + fi + LATEST_VERSION="${LATEST_TAG#v}" + LATEST_VERSION="${LATEST_VERSION%%-*}" + if [ "$(printf '%s\n' "$LATEST_VERSION" "$PKG_VERSION" | sort -V | tail -1)" != "$PKG_VERSION" ]; then + echo "::error::Version bump required: package.json version ($PKG_VERSION) is not greater than latest tag ($LATEST_TAG). Please bump the version in package.json." + exit 1 + fi + if [ "$PKG_VERSION" = "$LATEST_VERSION" ]; then + echo "::error::Version bump required: package.json version ($PKG_VERSION) equals latest tag ($LATEST_TAG). Please bump the version in package.json." + exit 1 + fi + echo "Version bump check passed: package.json is at $PKG_VERSION (latest tag: $LATEST_TAG)." diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 9ed98f5..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Release - -on: - push: - branches: [master] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: "22.x" - - run: npm install - - - name: get-package-details - id: package - uses: codex-team/action-nodejs-package-info@v1.1 - - name: install npm packall - run: npm install npm-pack-all - - - run: node node_modules/.bin/npm-pack-all - - uses: Klemensas/action-autotag@stable - id: update_tag - with: - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - tag_prefix: "v" - - name: Create Release - if: steps.update_tag.outputs.tagname - uses: actions/create-release@v1 - id: create_release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token - with: - tag_name: ${{ steps.update_tag.outputs.tagname }} - release_name: Release ${{ steps.update_tag.outputs.tagname }} - draft: false # Default value, but nice to set explicitly - prerelease: false # Default value, but nice to set explicitly - - name: Upload Release Asset - if: steps.update_tag.outputs.tagname - id: upload-release-asset - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing its ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps - asset_path: ./${{ steps.package.outputs.name }}-${{ steps.package.outputs.version }}.tgz - asset_name: ${{ steps.package.outputs.name }}-${{ steps.package.outputs.version }}.tgz - asset_content_type: application/tgz \ No newline at end of file diff --git a/.husky/post-checkout b/.husky/post-checkout new file mode 100755 index 0000000..302fdc6 --- /dev/null +++ b/.husky/post-checkout @@ -0,0 +1,40 @@ +#!/usr/bin/env sh +# When switching to a branch that doesn't exist on remote (e.g. newly created), +# pull and merge origin/main or origin/master into current branch. Does not push. + +# Only run on branch checkout (not file checkout) +if [ "$3" != "1" ]; then + exit 0 +fi + +# Skip if we don't have a remote +if ! git rev-parse --verify origin 2>/dev/null; then + exit 0 +fi + +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + +# Skip main/master - no need to merge base into these +case "$CURRENT_BRANCH" in + main|master) exit 0 ;; +esac + +# Only run when current branch does not exist on origin (treat as new local branch) +if git ls-remote --heads origin "$CURRENT_BRANCH" 2>/dev/null | grep -q .; then + echo "post-checkout: $CURRENT_BRANCH exists on origin, skipping merge." + exit 0 +fi + +# Prefer main, fallback to master +if git rev-parse --verify origin/main 2>/dev/null; then + BASE=origin/main +elif git rev-parse --verify origin/master 2>/dev/null; then + BASE=origin/master +else + exit 0 +fi + +echo "New branch detected: merging latest $BASE into $CURRENT_BRANCH (local only, not pushing)..." +git fetch origin +git merge "$BASE" --no-edit --no-ff +echo "Done. Merge is local only; push when ready." diff --git a/package-lock.json b/package-lock.json index 757e808..b523273 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "datasync-nodejs-sdk-boilerplate", - "version": "0.0.10", + "version": "0.0.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "datasync-nodejs-sdk-boilerplate", - "version": "0.0.10", + "version": "0.0.11", "license": "MIT", "dependencies": { "@contentstack/datasync-filesystem-sdk": "1.5.2", @@ -80,15 +80,15 @@ } }, "node_modules/@contentstack/utils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@contentstack/utils/-/utils-1.7.0.tgz", - "integrity": "sha512-wNWNt+wkoGJzCr5ZhAMKWJ5ND5xbD7N3t++Y6s1O+FB+AFzJszqCT740j6VqwjhQzw5sGfHoGjHIvlQA9dCcBw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@contentstack/utils/-/utils-1.8.0.tgz", + "integrity": "sha512-pqCFbn2dynSCW6LUD2AH74LIy32dxxe52OL+HpUxNVXV5doFyClkFjP9toqdAZ81VbCEaOc4WK+VS/RdtMpxDA==", "license": "MIT" }, "node_modules/@mongodb-js/saslprep": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.5.tgz", - "integrity": "sha512-k64Lbyb7ycCSXHSLzxVdb2xsKGPMvYZfCICXvDsI8Z65CeWQzTEKS4YmGbnqw+U9RBvLPTsB6UCmwkgsDTGWIw==", + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.6.tgz", + "integrity": "sha512-y+x3H1xBZd38n10NZF/rEBlvDOOMQ6LKUTHqr8R9VkJ+mmQOYtJFxIlkkK8fZrtOiL6VixbOBWMbZGBdal3Z1g==", "license": "MIT", "dependencies": { "sparse-bitfield": "^3.0.3" @@ -152,9 +152,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -459,9 +459,9 @@ } }, "node_modules/contentstack": { - "version": "3.26.4", - "resolved": "https://registry.npmjs.org/contentstack/-/contentstack-3.26.4.tgz", - "integrity": "sha512-NUe1Yz+NwmNJHTbSMr0tJ4YrerhHSaHPgptXFGxhTQkHG1d/2JDmjGeKocpA5ffO/x9JhgJmzrki+V4BsyQN4A==", + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/contentstack/-/contentstack-3.27.0.tgz", + "integrity": "sha512-2ZzVk1dO4AhgaiuPjLIzeDnQky/ElI02E4+tntX7xXQXgPEDWgogghoRMT0y0dFBcZthrZe1QChwYA9aCRSGpA==", "license": "MIT", "dependencies": { "@contentstack/utils": "^1.4.1", @@ -1558,9 +1558,9 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -1971,9 +1971,9 @@ } }, "node_modules/qs": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz", - "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", + "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" diff --git a/package.json b/package.json index efa5228..8ccb2a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "datasync-nodejs-sdk-boilerplate", - "version": "0.0.10", + "version": "0.0.11", "private": true, "scripts": { "start": "node ./bin/www",