Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
adbdf89
Merge pull request #141 from contentstack/staging
harshitha-cstk Mar 30, 2026
7cab71d
Merge pull request #143 from contentstack/main
cs-raj Mar 30, 2026
8581fa6
fix: request version bump
sunil-lakshman Apr 2, 2026
1a0d430
Merge pull request #144 from contentstack/fix/snyk-request-version-bump
sunil-lakshman Apr 6, 2026
fddda8e
Enh: Added cursor rules and skills
sunil-lakshman Apr 6, 2026
bacb1f0
Updated cursor rules as per new structure
sunil-lakshman Apr 7, 2026
9fa7935
Removed the reports
sunil-lakshman Apr 7, 2026
1b018fc
Merge pull request #145 from contentstack/enh/DX-5381
sunil-lakshman Apr 7, 2026
b345005
Added release version bump and changelog file
sunil-lakshman Apr 15, 2026
524f1d1
Merge pull request #147 from contentstack/fix/release_version_bump
cs-raj Apr 15, 2026
ab5144c
Merge pull request #146 from contentstack/development
cs-raj Apr 15, 2026
369dc64
fix: requirements.txt to reduce vulnerabilities
snyk-bot Apr 22, 2026
c29fca3
Merge pull request #149 from contentstack/snyk-fix-e6c7f9d976f131291a…
sunil-lakshman Apr 22, 2026
195faa5
enh: adopt development→main release flow, back-merge, and version checks
harshitha-cstk Apr 23, 2026
6136eae
Merge pull request #151 from contentstack/enh/dx-6155-adopt-new-relea…
harshitha-cstk Apr 24, 2026
978411d
Added urllib version bump
sunil-lakshman May 13, 2026
b324543
Merge pull request #152 from contentstack/fix/snyk-fix
sunil-lakshman May 13, 2026
59b63cc
Added branches support in entry variants
sunil-lakshman May 14, 2026
56a452d
Removed unused dependency so the package installs on Python 3.12+ an…
sunil-lakshman May 25, 2026
f058376
Merge pull request #154 from contentstack/enh/dx-7349
sunil-lakshman May 25, 2026
2869f36
Fixed merge conflits
sunil-lakshman Jun 1, 2026
24566e5
Merge pull request #157 from contentstack/fix/resolve-main-conflicts
sunil-lakshman Jun 1, 2026
22ab6b8
Merge pull request #155 from contentstack/development
harshitha-cstk Jun 1, 2026
b3eb74a
Merge pull request #158 from contentstack/main
harshitha-cstk Jun 1, 2026
edec155
feat: Added Endpoint Integration for CMA Python SDK
OMpawar-21 Jun 8, 2026
22b4750
Delete ENDPOINT_INTEGRATION.md
OMpawar-21 Jun 8, 2026
057e873
Merge pull request #159 from contentstack/enhc/DX-7277
OMpawar-21 Jun 8, 2026
ea960a9
updated skill files and agents
cs-raj Jun 16, 2026
33359c1
Merge pull request #160 from contentstack/fix/agents
cs-raj Jun 16, 2026
374049a
Merge branch 'main' into development
OMpawar-21 Jun 16, 2026
f1b882b
Merge pull request #162 from contentstack/fix/backmerge-16-06-2026
OMpawar-21 Jun 16, 2026
a3eefed
fix: add refresh_regions utility and auto-refresh regions.json at bui…
OMpawar-21 Jun 17, 2026
18c2eeb
fix: updated change log with the fix
OMpawar-21 Jun 17, 2026
50a5bb9
fix: change log date update
OMpawar-21 Jun 17, 2026
2f47761
Update CHANGELOG.md
OMpawar-21 Jun 18, 2026
3a84192
Merge pull request #163 from contentstack/fix/DX-9040
OMpawar-21 Jun 19, 2026
dec0e0d
issues-jira.yml
Aravind-Kumar-cstk Jun 19, 2026
f5be3cb
Merge pull request #165 from contentstack/main
harshitha-cstk Jun 19, 2026
b1c8525
Merge pull request #164 from contentstack/development
OMpawar-21 Jun 22, 2026
35372ad
feat: add asset scanning unit tests for _asset_scan_status param and …
OMpawar-21 Jun 25, 2026
49912d4
test: add dynamic-stack CMA SDK integration (sanity) suite
aniket-shikhare-cstk Jun 25, 2026
a591837
test: add asset-scanning (AM 2.0) integration coverage
aniket-shikhare-cstk Jun 26, 2026
4fbb827
fix(assets): send correct Content-Type for update and replace (v1.10.1)
aniket-shikhare-cstk Jun 26, 2026
d34dde2
test(integration): fix delete/bulk/branch cases + transient retries
aniket-shikhare-cstk Jun 26, 2026
b805b88
Update test_assets_unit.py
OMpawar-21 Jun 27, 2026
4c64ba7
fix(review): address PR #168 Copilot review comments
aniket-shikhare-cstk Jun 28, 2026
c0ca20c
fix(assets): replace() use save/restore for Content-Type header
aniket-shikhare-cstk Jun 29, 2026
b2eb8d1
fix(workflow): set entry to workflow stage before publish_request_app…
aniket-shikhare-cstk Jun 29, 2026
32d4a1a
fix(workflow): restore xfail on publish_request_approval with accurat…
aniket-shikhare-cstk Jun 29, 2026
2d301bd
fix(publish): remove xfail from test_publish_request_approval due to …
aniket-shikhare-cstk Jun 29, 2026
ee09fe8
Delete issues-jira.yml
Aravind-Kumar-cstk Jun 30, 2026
8ba9b5f
Merge pull request #167 from contentstack/enhc/DX-8751
reeshika-h Jul 3, 2026
8a597b0
Merge branch 'development' into test/cma-python-integration-rewrite
OMpawar-21 Jul 3, 2026
8975c51
Merge pull request #166 from contentstack/main
reeshika-h Jul 3, 2026
4bb93fb
Merge pull request #168 from contentstack/test/cma-python-integration…
reeshika-h Jul 3, 2026
b62d838
Merge pull request #169 from contentstack/development
reeshika-h Jul 6, 2026
268f427
Merge pull request #170 from contentstack/main
reeshika-h Jul 6, 2026
9304d8a
fix: remove hardcoded passwords in unit tests to resolve Snyk CWE-798…
OMpawar-21 Jul 8, 2026
fd911f8
Merge pull request #171 from contentstack/fix/Snyk-fix-08-06-2026
OMpawar-21 Jul 8, 2026
ea7abbe
Merge pull request #172 from contentstack/main
OMpawar-21 Jul 8, 2026
baadcb0
fix: version bump
OMpawar-21 Jul 8, 2026
5687fa5
Merge branch 'main' into fix/version-bump-8-7-26
OMpawar-21 Jul 8, 2026
8b7916d
Merge pull request #173 from contentstack/fix/version-bump-8-7-26
OMpawar-21 Jul 8, 2026
8d1b46e
Merge pull request #174 from contentstack/main
OMpawar-21 Jul 8, 2026
9d208b1
Merge branch 'development' into enh/dx-7265
OMpawar-21 Jul 16, 2026
1dc5d42
Update __init__.py
OMpawar-21 Jul 16, 2026
2bc2ce1
Merge pull request #153 from contentstack/enh/dx-7265
OMpawar-21 Jul 17, 2026
fc1d0a3
Merge pull request #175 from contentstack/development
naman-contentstack Jul 20, 2026
1228771
Merge pull request #176 from contentstack/main
naman-contentstack Jul 20, 2026
ce4a500
fix: bump setuptools to resolve Snyk vulnerability
OMpawar-21 Jul 22, 2026
09b3a5a
Merge pull request #177 from contentstack/fix/snyk-fix-22-07-2026
OMpawar-21 Jul 22, 2026
d40cb5f
Merge pull request #178 from contentstack/main
OMpawar-21 Jul 22, 2026
da76339
sca-scan.yml
Aravind-Kumar-cstk Aug 2, 2026
385f8aa
fix false positive hardcoded secrets
harshitha-cstk Aug 10, 2026
82da045
ci: install setuptools so coverage-badge can import pkg_resources
harshitha-cstk Aug 10, 2026
3ae7c9a
ci: pin setuptools<81 so coverage-badge can import pkg_resources
harshitha-cstk Aug 10, 2026
df34524
Merge pull request #181 from contentstack/fix/snyk-issues-secrets
harshitha-cstk Aug 10, 2026
44ddfd1
fix: move pylint to dev dependencies to resolve GPL-2.0 Snyk flag
OMpawar-21 Aug 10, 2026
eaea543
chore: bump version to 1.11.2
OMpawar-21 Aug 10, 2026
946d929
Merge pull request #183 from contentstack/main
OMpawar-21 Aug 10, 2026
93eff64
Merge branch 'main' into fix/snyk-pylint-gpl-dx8256
OMpawar-21 Aug 10, 2026
81d6307
Potential fix for pull request finding
OMpawar-21 Aug 11, 2026
0bf8891
docs: update pylint references to point to requirements-dev.txt
OMpawar-21 Aug 11, 2026
3a58ab1
Merge pull request #182 from contentstack/fix/snyk-pylint-gpl-dx8256
OMpawar-21 Aug 11, 2026
019098b
Merge pull request #184 from contentstack/main
OMpawar-21 Aug 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .cursor/rules/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Cursor (optional)

**Cursor** users: start at **[AGENTS.md](../../AGENTS.md)**. All conventions live in **`skills/*/SKILL.md`**.

This folder only points contributors to **`AGENTS.md`** so editor-specific config does not duplicate the canonical docs.
56 changes: 56 additions & 0 deletions .github/workflows/back-merge-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Opens a PR from main → development after changes land on main (back-merge).

name: Back-merge main to development

on:
push:
branches: [main]
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: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
git fetch origin development main

MAIN_SHA=$(git rev-parse origin/main)
DEV_SHA=$(git rev-parse origin/development)

if [ "$MAIN_SHA" = "$DEV_SHA" ]; then
echo "main and development are at the same commit; nothing to back-merge."
exit 0
fi

EXISTING=$(gh pr list --repo "${{ github.repository }}" \
--base development \
--head main \
--state open \
--json number \
--jq 'length')

if [ "$EXISTING" -gt 0 ]; then
echo "An open PR from main to development already exists; skipping."
exit 0
fi

gh pr create --repo "${{ github.repository }}" \
--base development \
--head main \
--title "chore: back-merge main into development" \
--body "Automated back-merge after changes landed on \`main\`. Review and merge to keep \`development\` in sync."

echo "Created back-merge PR main → development."
110 changes: 110 additions & 0 deletions .github/workflows/check-version-bump.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Release-affecting changes under contentstack_management/ or setup.py require
# __version__ + CHANGELOG.md updates aligned with the latest tag.

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
id: detect
run: |
FILES=$(git diff --name-only "${{ github.event.pull_request.base.sha }}" "${{ github.event.pull_request.head.sha }}")
echo "Changed files:"
echo "$FILES"

CODE_CHANGED=false
while IFS= read -r f; do
[ -z "$f" ] && continue
if [[ "$f" == contentstack_management/* ]] || [[ "$f" == "setup.py" ]]; then
CODE_CHANGED=true
break
fi
done <<< "$FILES"

INIT_CHANGED=false
CHANGELOG_CHANGED=false
echo "$FILES" | grep -qx 'contentstack_management/__init__.py' && INIT_CHANGED=true
echo "$FILES" | grep -qx 'CHANGELOG.md' && CHANGELOG_CHANGED=true

VERSION_FILES_OK=false
if [ "$INIT_CHANGED" = true ] && [ "$CHANGELOG_CHANGED" = true ]; then
VERSION_FILES_OK=true
fi

echo "code_changed=$CODE_CHANGED" >> "$GITHUB_OUTPUT"
echo "version_files_ok=$VERSION_FILES_OK" >> "$GITHUB_OUTPUT"

- name: Skip when no release-affecting code changed
if: steps.detect.outputs.code_changed != 'true'
run: |
echo "No contentstack_management or setup.py changes. Skipping version-bump check."
exit 0

- name: Fail when version files were not both updated
if: steps.detect.outputs.code_changed == 'true' && steps.detect.outputs.version_files_ok != 'true'
run: |
echo "::error::Bump __version__ in contentstack_management/__init__.py and add a ## vX.Y.Z section in CHANGELOG.md."
exit 1

- name: Validate version vs latest tag and changelog header
if: steps.detect.outputs.code_changed == 'true' && steps.detect.outputs.version_files_ok == 'true'
run: |
set -euo pipefail
PKG_VERSION=$(python3 <<'PY'
import re
text = open("contentstack_management/__init__.py").read()
m = re.search(r"^__version__\s*=\s*['\"]([^'\"]+)['\"]", text, re.MULTILINE)
if not m:
raise SystemExit("Could not read __version__ from contentstack_management/__init__.py")
print(m.group(1).strip())
PY
)

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 semver vs tag check."
CHANGELOG_HEAD=$(sed -nE 's/^## v?([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' CHANGELOG.md | head -1)
if [ -z "$CHANGELOG_HEAD" ]; then
echo "::error::Could not find a ## vX.Y.Z entry at the top of CHANGELOG.md."
exit 1
fi
if [ "$CHANGELOG_HEAD" != "$PKG_VERSION" ]; then
echo "::error::CHANGELOG top version ($CHANGELOG_HEAD) does not match __version__ ($PKG_VERSION)."
exit 1
fi
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__ ($PKG_VERSION) must be greater than latest tag ($LATEST_TAG)."
exit 1
fi
if [ "$PKG_VERSION" = "$LATEST_VERSION" ]; then
echo "::error::__version__ ($PKG_VERSION) must be strictly greater than latest tag version ($LATEST_VERSION)."
exit 1
fi

CHANGELOG_HEAD=$(sed -nE 's/^## v?([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' CHANGELOG.md | head -1)
if [ -z "$CHANGELOG_HEAD" ]; then
echo "::error::Could not find a ## vX.Y.Z entry at the top of CHANGELOG.md."
exit 1
fi
if [ "$CHANGELOG_HEAD" != "$PKG_VERSION" ]; then
echo "::error::CHANGELOG top version ($CHANGELOG_HEAD) does not match __version__ ($PKG_VERSION)."
exit 1
fi
echo "Version bump check passed: __version__ and CHANGELOG at $PKG_VERSION (latest tag: $LATEST_TAG)."
31 changes: 0 additions & 31 deletions .github/workflows/issues-jira.yml

This file was deleted.

5 changes: 4 additions & 1 deletion .github/workflows/sca-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ on:
jobs:
security-sca:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@master
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/python@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --fail-on=all --all-projects --skip-unresolved
args: --fail-on=all --all-projects
json: true
continue-on-error: true
- uses: contentstack/sca-policy@main
2 changes: 1 addition & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt # If you have a requirements file
pip install coverage pytest coverage-badge
pip install coverage pytest coverage-badge "setuptools<81"


- name: Run tests and coverage
Expand Down
15 changes: 12 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,17 @@ tests/config/default.yml
.vscode/settings.json
run.py
tests/resources/.DS_Store
.talismanrc
tests/.DS_Store
tests/resources/.DS_Store
.DS_Store
.talismanrc
*/data/regions.json
# Local backup of legacy tests (do not commit)

# --- CMA integration suite: do not track ---
docs/
tests_backup_legacy/
tests/integration/report/
tests/integration/.env
tests/integration/.env.example
# Timestamped reports written at repo root
cma-python-report-*.html
api-requests-*.txt
4 changes: 4 additions & 0 deletions .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -406,3 +406,7 @@ fileignoreconfig:
- filename: tests/mock/assets/test_assets_mock.py
checksum: 12c9091bb88c0c12712f046b29fb4a9dce3b95ecc45f4ea46bbc3fd4529742a0
version: "1.0"
fileignoreconfig:
- filename: tests/integration/framework/capture.py
checksum: c9680c4ee3e1def0765fd89767fa1383aee5d195222fa021a19618607373047c
version: "1.0"
86 changes: 86 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Contentstack Management Python – Agent guide

**Universal entry point** for contributors and AI agents. Detailed conventions live in **`skills/*/SKILL.md`**.

## What this repo is

| Field | Detail |
|--------|--------|
| **Name:** | **`contentstack-management`** (PyPI) — [contentstack/contentstack-management-python](https://github.com/contentstack/contentstack-management-python) |
| **Purpose:** | Python client for the **Content Management API (CMA)**: organizations, stacks, content types, entries, assets, webhooks, workflows, OAuth, and related resources. Uses **`requests`** via **`_APIClient`**. |

## Tech stack (at a glance)

| Area | Details |
|------|---------|
| Language | Python ≥ 3.9 (`setup.py` `python_requires`) |
| Build | `setuptools` / `setup.py`; package `contentstack_management` |
| HTTP | `requests`, `requests-toolbelt`, `urllib3` |
| Tests | `pytest` — `tests/integration` (live e2e / sanity, dynamic stack), `tests/unit`, `tests/mock`, `tests/api` (legacy, superseded by `tests/integration`) |
| Lint / coverage | `pylint`, `coverage` (see `requirements-dev.txt`) |
| Secrets / hooks | Talisman, Snyk (see `README.md` development setup) |

## Source layout

| Path | Role |
|------|------|
| `contentstack_management/contentstack.py` | **`Client`**, **`Region`**, endpoint construction, **`user_agents`**, optional **OAuth** wiring |
| `contentstack_management/_api_client.py` | **`_APIClient`** — HTTP calls, retries, optional **OAuth** interceptor |
| `contentstack_management/stack/stack.py` | **Stack**-scoped CMA operations |
| `contentstack_management/*/` | Domain modules (entries, assets, webhooks, taxonomies, …) |
| `contentstack_management/__init__.py` | Public exports |
| `tests/integration/` | **Live e2e / sanity suite** (pytest). Self-contained: creates a fresh stack per run, exercises every SDK method (positive/negative/edge), tears it down. Own `framework/` + `data/`; config in `tests/integration/.env`. |
| `tests/cred.py` | **`get_credentials()`** — **dotenv** + env vars for the legacy `tests/api` / `tests/mock` suites |

## Commands (quick reference)

| Command Type | Command |
|---|---|
| Install | `pip install -e ".[dev]"` |
| **Sanity / e2e (live)** | `pytest tests/integration` — dynamically creates a stack, runs the full suite, tears it down. Needs `tests/integration/.env` (`EMAIL`, `PASSWORD`, `HOST`, `ORGANIZATION`). Writes a timestamped HTML report + cURL log to the repo root. |
| Sanity, keep stack | `DELETE_DYNAMIC_RESOURCES=false pytest tests/integration` (preserve the created stack for debugging) |
| Sanity, one resource | `pytest tests/integration/api/test_12_content_type.py` |
| Test (unit) | `pytest tests/unit/ -v` |
| Test (mock) | `pytest tests/mock/ -v` |
| Test (legacy API, live) | `pytest tests/api/ -v` (needs `.env` — see `tests/cred.py`) |
| Coverage (CI) | `coverage run -m pytest tests/unit/` |
| Lint | `pylint contentstack_management/` |

> **CI note:** `.github/workflows/unit-test.yml` runs **only `tests/unit/`** (no credentials). The `tests/integration` sanity suite is run manually (or via a credential-gated job) because it provisions real stacks.

## Environment variables

**Sanity / e2e suite** (`tests/integration`) — configured via **`tests/integration/.env`** (gitignored). No pre-existing stack/UIDs needed; the suite creates everything at runtime.

| Var | Required | Purpose |
|-----|----------|---------|
| `EMAIL`, `PASSWORD` | ✅ | Login for the run (a **non-2FA** account) |
| `HOST` | ✅ | API host (e.g. `api.contentstack.io`) |
| `ORGANIZATION` | ✅ | Org the dynamic test stack is created in |
| `MFA_SECRET` | — | TOTP secret (for the OAuth/2FA account, not the primary login) |
| `DELETE_DYNAMIC_RESOURCES` | — | `false` keeps the created stack for debugging (default deletes) |
| `CLIENT_ID`, `APP_ID`, `REDIRECT_URI` | — | OAuth tests |
| `PERSONALIZE_HOST` | — | Personalize project for variant tests |

**Legacy `tests/api` / `tests/mock`** — loaded via **`tests/cred.py`** (`load_dotenv()`): `HOST`, `APIKEY`, `AUTHTOKEN`, `MANAGEMENT_TOKEN`, `ORG_UID`, and resource UIDs. See that file for the full list.

Do not commit secrets. `tests/integration/.env`, `docs/`, and the repo-root `cma-python-report-*.html` / `api-requests-*.txt` are gitignored.

## Where the documentation lives: skills

| Skill | Path | What it covers |
|-------|------|----------------|
| **Development workflow** | [`skills/dev-workflow/SKILL.md`](skills/dev-workflow/SKILL.md) | Install, pytest suites, packaging version, pylint, hooks, PR baseline |
| **Contentstack Management (SDK)** | [`skills/contentstack-management/SKILL.md`](skills/contentstack-management/SKILL.md) | **`Client`**, **`Stack`**, **`_APIClient`**, CMA resources, OAuth, CMA docs |
| **Python style & repo layout** | [`skills/python-style/SKILL.md`](skills/python-style/SKILL.md) | Package layout, naming, imports via **`_APIClient`**, secrets in logs |
| **Testing** | [`skills/testing/SKILL.md`](skills/testing/SKILL.md) | pytest unit / API / mock, **`tests/cred.py`**, env hygiene |
| **Code review** | [`skills/code-review/SKILL.md`](skills/code-review/SKILL.md) | PR checklist—public API, HTTP/auth, tests, security |
| **Framework / HTTP** | [`skills/framework/SKILL.md`](skills/framework/SKILL.md) | **`requests`**, retries, OAuth interceptor, where to change transport |

An index with “when to use” hints is in [`skills/README.md`](skills/README.md).

## Using Cursor (optional)

If you use **Cursor**, [`.cursor/rules/README.md`](.cursor/rules/README.md) only points to **`AGENTS.md`**—same docs as everyone else.

Product docs: [Content Management API](https://www.contentstack.com/docs/developers/apis/content-management-api/).
Loading
Loading