Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d8a32cc
Merge pull request #52 from contentstack/development
harshithad0703 Jan 5, 2026
b8b8048
fix snyk issues
harshithad0703 Jan 5, 2026
c01a387
Merge pull request #55 from contentstack/fix/snyk
harshithad0703 Jan 5, 2026
8ed584b
remove unused dependency
harshithad0703 Feb 3, 2026
5dd050f
upgrade dependencies
harshithad0703 Feb 5, 2026
e375d8c
Merge branch 'master' into fix/snyk
cs-raj Feb 9, 2026
945c720
Merge pull request #59 from contentstack/fix/snyk
harshithad0703 Feb 9, 2026
5c75921
Update sca-scan.yml
dhavaljain999 Mar 2, 2026
2241d51
snyk fix: Fix Allocation of Resources Without Limits or Throttling
harshithad0703 Mar 26, 2026
8c4c2a4
Add GitHub workflows for branch checks and version bump validation
harshithad0703 Mar 26, 2026
dd95d27
remove check branch workflow
harshithad0703 Mar 26, 2026
c0786d6
Update post-checkout hook to skip 'development' branch check
harshithad0703 Mar 26, 2026
2b180ad
Refine version bump workflow to focus solely on package.json; removed…
harshithad0703 Mar 26, 2026
295f19d
Merge pull request #63 from contentstack/fix/dx-4850-snyk-fix
harshithad0703 Mar 26, 2026
3f187ae
fix snyk issues
harshithad0703 Apr 2, 2026
afdc98e
Merge pull request #65 from contentstack/fix/snyk-issues
harshithad0703 Apr 6, 2026
b0b730f
Add AGENTS.md, skills README, and individual skill guides.
harshithad0703 Apr 10, 2026
e018e2f
Merge pull request #66 from contentstack/feat/dx-5406-cursor-rules-an…
harshithad0703 Apr 10, 2026
4d73700
Update package versions
harshithad0703 May 20, 2026
0e59f7e
Merge pull request #68 from contentstack/fix/snyk-issues-fix
harshithad0703 May 20, 2026
a5a2bc3
issues-jira.yml
Aravind-Kumar-cstk Jun 19, 2026
6a9e036
Fix: Upgrade dependencies
harshithad0703 Jun 24, 2026
e10a01c
version bump
harshithad0703 Jun 24, 2026
925d524
Merge pull request #70 from contentstack/fix/snyk-issues
harshithad0703 Jun 24, 2026
c86365b
upgrade dependency
harshithad0703 Jun 24, 2026
940e742
Merge branch 'master' into fix/snyk-issues
harshithad0703 Jun 24, 2026
88cd9dd
Merge pull request #71 from contentstack/fix/snyk-issues
harshithad0703 Jun 24, 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.
54 changes: 54 additions & 0 deletions .github/workflows/back-merge-pr.yml
Original file line number Diff line number Diff line change
@@ -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."
79 changes: 79 additions & 0 deletions .github/workflows/check-version-bump.yml
Original file line number Diff line number Diff line change
@@ -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)."
121 changes: 104 additions & 17 deletions .github/workflows/issues-jira.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,117 @@ name: Create Jira Ticket for Github Issue

on:
issues:
types: [opened]
types: [opened, reopened]

jobs:
issue-jira:
runs-on: ubuntu-latest
steps:
- name: Create Jira Issue
id: create_jira
uses: actions/github-script@v9
with:
script: |
const baseUrl = process.env.JIRA_BASE_URL;
const userEmail = process.env.JIRA_USER_EMAIL;
const jiraToken = process.env.JIRA_API_TOKEN;
const jiraProject = process.env.JIRA_PROJECT;
const jiraIssueType = process.env.JIRA_ISSUE_TYPE;
const jiraFields = JSON.parse(process.env.ISSUES_JIRA_FIELDS);

let requestBody = JSON.stringify({
fields: {
...jiraFields,
"project": {
"key": jiraProject
},
"issuetype": {
"name": jiraIssueType
},
"summary": "Github | Issue | ${{ github.event.repository.name }} | ${{ github.event.issue.title }}",
"description": {
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Github Issue",
"marks": [
{
"type": "strong"
}
]
},
{
"type": "text",
"text": ": "
},
{
"type": "text",
"text": "${{ github.event.issue.html_url }}",
"marks": [
{
"type": "link",
"attrs": {
"href": "${{ github.event.issue.html_url }}"
}
}
]
}
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Description",
"marks": [
{
"type": "strong"
}
]
},
{
"type": "text",
"text": ":"
}
]
},
{
"type": "codeBlock",
"content": [
{
"type": "text",
"text": `${{ github.event.issue.body }}`
}
]
}
]
}
}
});

- name: Login to Jira
uses: atlassian/gajira-login@master
const response = await fetch(`${baseUrl}/rest/api/3/issue`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${btoa(userEmail + ":" + jiraToken)}`
},
body: requestBody
});
if (!response.ok) {
throw new Error(`JIRA API error! Status: ${response.status}`);
}
const data = await response.json();
console.log('Jira Issue Created:', data.key);
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}

- name: Create Jira Issue
id: create_jira
uses: atlassian/gajira-create@master
with:
project: ${{ secrets.JIRA_PROJECT }}
issuetype: ${{ secrets.JIRA_ISSUE_TYPE }}
summary: Github | Issue | ${{ github.event.repository.name }} | ${{ github.event.issue.title }}
description: |
*GitHub Issue:* ${{ github.event.issue.html_url }}

*Description:*
${{ github.event.issue.body }}
fields: "${{ secrets.ISSUES_JIRA_FIELDS }}"
JIRA_PROJECT: ${{ secrets.JIRA_PROJECT }}
JIRA_ISSUE_TYPE: ${{ secrets.JIRA_ISSUE_TYPE }}
ISSUES_JIRA_FIELDS: "${{ secrets.ISSUES_JIRA_FIELDS }}"
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
name: Release

on:
push:
branches: [master]
release:
types: [created]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: "22.x"
node-version: "18.x"
- run: npm install

- name: get-package-details
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/sca-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@ jobs:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --all-projects --fail-on=all
json: true
continue-on-error: true
- uses: contentstack/sca-policy@main
40 changes: 40 additions & 0 deletions .husky/post-checkout
Original file line number Diff line number Diff line change
@@ -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."
48 changes: 48 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Contentstack DataSync Node.js Website Boilerplate – 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/datasync-nodejs-website-boilerplate](https://github.com/contentstack/datasync-nodejs-website-boilerplate) |
| **Purpose:** | Express app that serves a site from Contentstack DataSync–backed content (filesystem or MongoDB SDK), with Nunjucks views and synced data under the configured content store. |
| **Out of scope (if any):** | Not the DataSync sync pipeline itself (webhook listener, manager); this repo is the website layer on top of synced data. |

## Tech stack (at a glance)

| Area | Details |
|------|---------|
| Language | JavaScript (Node.js), CommonJS. Conventions: `skills/javascript-style/SKILL.md`. |
| Build | No compile step; run from source. Install dependencies with npm. |
| Tests | No automated test script in `package.json` today. |
| Lint / coverage | ESLint 5 with `.eslintrc.js` (strict rule set). No coverage tool configured. |
| Other | Express 5, Nunjucks, `@contentstack/datasync-filesystem-sdk` / `@contentstack/datasync-mongodb-sdk`, `contentstack` npm package. Optional: Husky hooks (Snyk, Talisman). |

## Commands (quick reference)

| Command type | Command |
|--------------|---------|
| Install deps | `npm install` |
| Run locally | `npm start` (uses `bin/www`; `NODE_ENV` selects `config/<env>.js`, default `development`) |
| Lint | `npx eslint .` |
| Husky setup | `npm run pre-commit` |

CI and automation: [.github/workflows/check-version-bump.yml](.github/workflows/check-version-bump.yml), [.github/workflows/sca-scan.yml](.github/workflows/sca-scan.yml), [.github/workflows/policy-scan.yml](.github/workflows/policy-scan.yml), [.github/workflows/codeql-analysis.yml](.github/workflows/codeql-analysis.yml), [.github/workflows/issues-jira.yml](.github/workflows/issues-jira.yml).

## Where the documentation lives: skills

| Skill | Path | What it covers |
|-------|------|----------------|
| Development workflow | `skills/dev-workflow/SKILL.md` | Install, run, hooks, CI expectations, version bumps on PRs |
| JavaScript style | `skills/javascript-style/SKILL.md` | CommonJS patterns, ESLint, matching existing file style |
| DataSync website app | `skills/datasync-website/SKILL.md` | Express entry points, Stack/content store, config and routes |
| Testing | `skills/testing/SKILL.md` | Current test posture; adding tests safely |
| Code review | `skills/code-review/SKILL.md` | PR checklist aligned with this repo |

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

## Using Cursor (optional)

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