diff --git a/.github/workflows/back-merge-pr.yml b/.github/workflows/back-merge-pr.yml new file mode 100644 index 0000000..02b378c --- /dev/null +++ b/.github/workflows/back-merge-pr.yml @@ -0,0 +1,54 @@ +name: Back-merge master to development + +on: + push: + branches: + - master + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + +jobs: + open-back-merge-pr: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Open back-merge PR if needed + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + BASE_BRANCH="development" + SOURCE_BRANCH="master" + + git fetch origin "$BASE_BRANCH" "$SOURCE_BRANCH" + + if ! git show-ref --verify --quiet "refs/remotes/origin/$BASE_BRANCH"; then + echo "Base branch '$BASE_BRANCH' does not exist on origin; skipping." + exit 0 + fi + + SOURCE_SHA=$(git rev-parse "origin/$SOURCE_BRANCH") + BASE_SHA=$(git rev-parse "origin/$BASE_BRANCH") + + if [ "$SOURCE_SHA" = "$BASE_SHA" ]; then + echo "$SOURCE_BRANCH and $BASE_BRANCH are at the same commit; nothing to back-merge." + exit 0 + fi + + EXISTING=$(gh pr list --repo "${{ github.repository }}" --base "$BASE_BRANCH" --head "$SOURCE_BRANCH" --state open --json number --jq 'length') + + if [ "$EXISTING" -gt 0 ]; then + echo "An open PR from $SOURCE_BRANCH to $BASE_BRANCH already exists; skipping." + exit 0 + fi + + gh pr create --repo "${{ github.repository }}" --base "$BASE_BRANCH" --head "$SOURCE_BRANCH" --title "chore: back-merge $SOURCE_BRANCH into $BASE_BRANCH" --body "Automated back-merge after changes landed on \\`$SOURCE_BRANCH\\`. Review and merge to keep \\`$BASE_BRANCH\\` in sync." + + echo "Created back-merge PR $SOURCE_BRANCH -> $BASE_BRANCH." diff --git a/.github/workflows/check-branch.yml b/.github/workflows/check-branch.yml deleted file mode 100644 index e79864e..0000000 --- a/.github/workflows/check-branch.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: 'Check Branch' - -on: - pull_request: - -jobs: - check_branch: - runs-on: ubuntu-latest - steps: - - name: Comment PR - if: github.base_ref == 'master' && github.head_ref != 'staging' - uses: thollander/actions-comment-pull-request@v2 - with: - message: | - We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the next branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch. - - name: Check branch - if: github.base_ref == 'master' && github.head_ref != 'staging' - run: | - echo "ERROR: We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the next branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch." - exit 1 \ No newline at end of file diff --git a/.github/workflows/check-version-bump.yml b/.github/workflows/check-version-bump.yml new file mode 100644 index 0000000..35a58c2 --- /dev/null +++ b/.github/workflows/check-version-bump.yml @@ -0,0 +1,79 @@ +name: Check Version Bump + +on: + pull_request: + +jobs: + version-bump: + name: Version & Changelog 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 'lib/contentstack/version.rb' && VERSION_FILES_CHANGED=true + echo "$FILES" | grep -qx 'CHANGELOG.md' && VERSION_FILES_CHANGED=true + echo "version_files_changed=$VERSION_FILES_CHANGED" >> $GITHUB_OUTPUT + # Only lib/ counts as release-affecting; .github/ and spec/ do not + CODE_CHANGED=false + echo "$FILES" | grep -qE '^lib/' && 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 spec/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 lib/contentstack/version.rb and add an entry in CHANGELOG.md." + exit 1 + + - name: Check version bump + if: steps.detect.outputs.code_changed == 'true' && steps.detect.outputs.version_files_changed == 'true' + run: | + set -e + GEM_VERSION=$(sed -n 's/.*VERSION = "\(.*\)".*/\1/p' lib/contentstack/version.rb) + if [ -z "$GEM_VERSION" ]; then + echo "::error::Could not read version from lib/contentstack/version.rb" + 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" "$GEM_VERSION" | sort -V | tail -1)" != "$GEM_VERSION" ]; then + echo "::error::Version bump required: lib/contentstack/version.rb ($GEM_VERSION) is not greater than latest tag ($LATEST_TAG). Please bump Contentstack::VERSION." + exit 1 + fi + if [ "$GEM_VERSION" = "$LATEST_VERSION" ]; then + echo "::error::Version bump required: lib/contentstack/version.rb ($GEM_VERSION) equals latest tag ($LATEST_TAG). Please bump Contentstack::VERSION." + exit 1 + fi + CHANGELOG_VERSION=$(sed -nE 's/^## Version ([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' CHANGELOG.md | head -1) + if [ -z "$CHANGELOG_VERSION" ]; then + echo "::error::Could not find a version entry in CHANGELOG.md (expected line like '## Version 1.0.0')." + exit 1 + fi + if [ "$CHANGELOG_VERSION" != "$GEM_VERSION" ]; then + echo "::error::CHANGELOG version mismatch: CHANGELOG.md top version ($CHANGELOG_VERSION) does not match lib/contentstack/version.rb ($GEM_VERSION). Please add or update the CHANGELOG entry for $GEM_VERSION." + exit 1 + fi + echo "Version bump check passed: lib/contentstack/version.rb and CHANGELOG.md are at $GEM_VERSION (latest tag: $LATEST_TAG)." diff --git a/.gitignore b/.gitignore index 5169614..43e8c09 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ test doc spec-integration coverage +spec/.env.test \.yardoc .DS_Store .bundle/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 4512a51..f1b5413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## CHANGELOG +## Version 0.8.5 +### Date: 5th-June-2026 + ### Deprecated + - `Query#include_draft` is deprecated. The Content Delivery API returns published content only; the `include_draft` query parameter has no effect. Use Live Preview with the Preview Service to preview unpublished entries, or the Content Management API to work with draft content. + ## Version 0.8.4 ### Date: 15th-April-2026 ### Security and Compatibility diff --git a/Gemfile.lock b/Gemfile.lock index 490a9c9..8fa4794 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - contentstack (0.8.4) + contentstack (0.8.5) activesupport (>= 3.2) contentstack_utils (~> 1.2) @@ -39,7 +39,7 @@ GEM hashdiff (1.2.1) i18n (1.14.8) concurrent-ruby (~> 1.0) - json (2.19.5) + json (2.19.7) logger (1.7.0) minitest (6.0.6) drb (~> 2.0) @@ -91,7 +91,7 @@ GEM addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - yard (0.9.43) + yard (0.9.44) PLATFORMS aarch64-linux-gnu @@ -111,5 +111,49 @@ DEPENDENCIES webmock (~> 3.26.0) yard (~> 0.9.38) +CHECKSUMS + activesupport (8.1.3) sha256=21a5e0dfbd4c3ddd9e1317ec6a4d782fa226e7867dc70b0743acda81a1dca20e + addressable (2.9.0) sha256=7fdf6ac3660f7f4e867a0838be3f6cf722ace541dd97767fa42bc6cfa980c7af + base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b + bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd + concurrent-ruby (1.3.6) sha256=6b56837e1e7e5292f9864f34b69c5a2cbc75c0cf5338f1ce9903d10fa762d5ab + connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a + contentstack (0.8.5) + contentstack_utils (1.2.3) sha256=cf2f5f996eb487559fd2d7d48a99262710f53dec62c84c6e325b9a598cd31ba7 + crack (1.0.1) sha256=ff4a10390cd31d66440b7524eb1841874db86201d5b70032028553130b6d4c7e + diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962 + docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e + drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373 + hashdiff (1.2.1) sha256=9c079dbc513dfc8833ab59c0c2d8f230fa28499cc5efb4b8dd276cf931457cd1 + i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5 + json (2.19.7) sha256=fe432c8639f6efff69f9d73b518a3705d9581ab93156f981ea72806e1e5bcc3e + logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203 + minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1 + nokogiri (1.19.3-aarch64-linux-gnu) sha256=46b89e5d7b9e844c2ee360794240c6ea2a4e6fa0c5892a4ed487db621224b639 + nokogiri (1.19.3-aarch64-linux-musl) sha256=8392dfdcd21be7a94dbbe9ccc138dea01b97b24cb2dc02a114ca98bfb1d9a0b7 + nokogiri (1.19.3-arm-linux-gnu) sha256=3919d5ffc334ad778a4a9eb88fda7dcb8b1fb58c8a52ac640c6dcd2f038e774f + nokogiri (1.19.3-arm-linux-musl) sha256=9ce1cb6346bb9c67b1550eb537aa183ead91e4b6eadb2f36ade02d8dd2a79fb6 + nokogiri (1.19.3-arm64-darwin) sha256=71b9bd424b1b7abc18b05052a1a3cfd3627abdca62be280854cc411791357e42 + nokogiri (1.19.3-x86_64-darwin) sha256=77f3fba57d46c53ab31e62fc6c28f705109d1bf6264356c76f132b2be5728d4d + nokogiri (1.19.3-x86_64-linux-gnu) sha256=2f5078620fe12e83669b5b17311b32532a8153d02eee7ad06948b926d6080976 + nokogiri (1.19.3-x86_64-linux-musl) sha256=248c906d2166eca5efb56d52fdee5f9a1f51d69a72e2b64fdac647b4ce39ea3f + prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85 + public_suffix (7.0.5) sha256=1a8bb08f1bbea19228d3bed6e5ed908d1cb4f7c2726d18bd9cadf60bc676f623 + racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f + rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142 + rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587 + rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d + rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836 + rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47 + rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c + securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 + simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5 + simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246 + simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428 + tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b + uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6 + webmock (3.26.2) sha256=774556f2ea6371846cca68c01769b2eac0d134492d21f6d0ab5dd643965a4c90 + yard (0.9.44) sha256=eb087e9b631ccd887b049f303d489963945452d5e2a7eb49a5a74a7cf6887f28 + BUNDLED WITH - 2.5.22 + 4.0.11 diff --git a/lib/contentstack/query.rb b/lib/contentstack/query.rb index 87bf22b..28115a8 100644 --- a/lib/contentstack/query.rb +++ b/lib/contentstack/query.rb @@ -565,16 +565,19 @@ def include_embedded_items() self end - # Include objects in 'Draft' mode in response - # - # Example - # - # @query = @stack.content_type('product').query - # @query.include_draft - # - # @return [Contentstack::Query] - def include_draft(flag=true) - @query[:include_draft] = flag + # @deprecated since 0.8.5 The Content Delivery API returns published content only. + # Unpublished or draft entries are not available through CDA queries. Use Live Preview + # with the Preview Service, or the Content Management API, to access unpublished content. + # + # @return [Contentstack::Query] + def include_draft(_flag=true) + warn( + "Contentstack: Query#include_draft is deprecated and has no effect on the Content " \ + "Delivery API, which returns published content only. To preview unpublished entries, " \ + "use Live Preview with the Preview Service. To manage or fetch draft entries, use " \ + "the Content Management API.", + uplevel: 1 + ) self end diff --git a/lib/contentstack/version.rb b/lib/contentstack/version.rb index 9afb23a..684bf20 100644 --- a/lib/contentstack/version.rb +++ b/lib/contentstack/version.rb @@ -1,3 +1,3 @@ module Contentstack - VERSION = "0.8.4" + VERSION = "0.8.5" end diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md index 7500a2e..edc612c 100644 --- a/skills/code-review/SKILL.md +++ b/skills/code-review/SKILL.md @@ -32,7 +32,7 @@ description: Use when authoring or reviewing a pull request for contentstack-rub ### Process notes -- **`master`** is protected by **`.github/workflows/check-branch.yml`**; follow team flow (**`staging`** → **`master`**) for production promotion. +- Follow direct release flow **`development` -> `master`** (no `staging` handoff in the release path). - Run **`bundle exec rspec`** locally; CI may not run the full suite on every PR in this repository. ## References diff --git a/skills/dev-workflow/SKILL.md b/skills/dev-workflow/SKILL.md index 8f93c0f..621ce61 100644 --- a/skills/dev-workflow/SKILL.md +++ b/skills/dev-workflow/SKILL.md @@ -28,7 +28,7 @@ description: Use when setting up the repo, running tests or docs, choosing branc ### Branches and PRs -- Default integration branch is typically **`development`** (confirm on GitHub). **`master`** merges are restricted: `.github/workflows/check-branch.yml` blocks PRs into `master` unless the head branch is **`staging`**—follow org process for promotion. +- Default integration branch is typically **`development`** (confirm on GitHub). Release PRs go directly **`development` -> `master`**; `staging` is not part of the release promotion flow. - Keep PRs focused; mention breaking API or Ruby version requirement changes in the description. ### Before you push diff --git a/skills/testing/SKILL.md b/skills/testing/SKILL.md index d5a4dfa..5f3ea2b 100644 --- a/skills/testing/SKILL.md +++ b/skills/testing/SKILL.md @@ -30,7 +30,7 @@ description: Use when writing or fixing RSpec examples, WebMock stubs, JSON fixt ### Helpers -- **`create_client`** and **`create_preview_client`** in **`spec_helper`** build clients using **`ENV['API_KEY']`**, **`ENV['DELIVERY_TOKEN']`**, **`ENV['ENVIRONMENT']`** — tests should not rely on real credentials; stubs supply responses. +- **`create_client`** and **`create_preview_client`** in **`spec_helper`** build clients using **`ENV['API_KEY']`**, **`ENV['DELIVERY_TOKEN']`**, **`ENV['ENVIRONMENT']`**. Copy **`spec/.env.test.example`** to **`spec/.env.test`** (gitignored) for local runs without exporting env vars; CLI/env values already set take precedence. Tests use WebMock stubs and do not require live API calls. ### Coverage diff --git a/spec/.env.test.example b/spec/.env.test.example new file mode 100644 index 0000000..553c8af --- /dev/null +++ b/spec/.env.test.example @@ -0,0 +1,10 @@ +# Copy to spec/.env.test and fill in your stack credentials. +# spec/.env.test is gitignored — do not commit real tokens. +# +# bundle exec rspec + +API_KEY=your_stack_api_key +DELIVERY_TOKEN=your_delivery_token +ENVIRONMENT=development +# Optional: only needed for custom CDN host tests +# HOST=cdn.contentstack.io diff --git a/spec/query_spec.rb b/spec/query_spec.rb index c845c4f..eaab7a6 100644 --- a/spec/query_spec.rb +++ b/spec/query_spec.rb @@ -165,8 +165,13 @@ expect(data.first.fields[:locale]).not_to be nil end - it "should get data using `include_draft` method" do - data = category_query.include_draft.fetch + it "warns when `include_draft` is called and does not send include_draft to the API" do + query = category_query + expect { + query.include_draft + }.to output(/Query#include_draft is deprecated/).to_stderr + expect(query.query).not_to have_key(:include_draft) + data = query.fetch expect(data.length).to eq 5 end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2934c22..bf556d3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -16,6 +16,8 @@ require 'webmock/rspec' WebMock.disable_net_connect!(allow_localhost: true) +require_relative 'support/load_test_env' + require 'simplecov' SimpleCov.start diff --git a/spec/support/load_test_env.rb b/spec/support/load_test_env.rb new file mode 100644 index 0000000..1cfe3c4 --- /dev/null +++ b/spec/support/load_test_env.rb @@ -0,0 +1,23 @@ +# Loads optional local test credentials from spec/.env.test (gitignored). +# Existing ENV values are not overwritten, so CLI exports still take precedence. +module ContentstackTestEnv + ENV_FILE = File.expand_path("../.env.test", __dir__).freeze + + def self.load! + return unless File.file?(ENV_FILE) + + File.foreach(ENV_FILE) do |line| + line = line.strip + next if line.empty? || line.start_with?("#") + + key, value = line.split("=", 2) + next if key.nil? || value.nil? + + key = key.strip + value = value.strip.delete_prefix('"').delete_suffix('"') + ENV[key] = value unless ENV.key?(key) && !ENV[key].to_s.empty? + end + end +end + +ContentstackTestEnv.load!