Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
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."
20 changes: 0 additions & 20 deletions .github/workflows/check-branch.yml

This file was deleted.

117 changes: 117 additions & 0 deletions .github/workflows/check-version-bump.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Release-affecting changes under Contentstack.Management*/ or Directory.Build.props / core csproj
# require Directory.Build.props Version + CHANGELOG.md updates vs 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
case "$f" in
Contentstack.Management.Core.Unit.Tests/*|Contentstack.Management.Core.Tests/*)
continue
;;
esac
if [[ "$f" == "Directory.Build.props" ]] || \
[[ "$f" == Contentstack.Management.Core/* ]] || \
[[ "$f" == Contentstack.Management.ASPNETCore/* ]]; then
CODE_CHANGED=true
break
fi
done <<< "$FILES"

PROPS_CHANGED=false
CHANGELOG_CHANGED=false
echo "$FILES" | grep -qx 'Directory.Build.props' && PROPS_CHANGED=true
echo "$FILES" | grep -qx 'CHANGELOG.md' && CHANGELOG_CHANGED=true

VERSION_FILES_OK=false
if [ "$PROPS_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 management SDK / version props 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 Directory.Build.props and add a ## [vX.Y.Z] section at the top of 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
PROJ_VERSION=$(python3 <<'PY'
import re
text = open("Directory.Build.props").read()
m = re.search(r"<Version>\s*([^<]+)\s*</Version>", text)
if not m:
raise SystemExit("Could not read <Version> from Directory.Build.props")
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" != "$PROJ_VERSION" ]; then
echo "::error::CHANGELOG top version ($CHANGELOG_HEAD) does not match Directory.Build.props Version ($PROJ_VERSION)."
exit 1
fi
exit 0
fi

LATEST_VERSION="${LATEST_TAG#v}"
LATEST_VERSION="${LATEST_VERSION%%-*}"
if [ "$(printf '%s\n' "$LATEST_VERSION" "$PROJ_VERSION" | sort -V | tail -1)" != "$PROJ_VERSION" ]; then
echo "::error::Version ($PROJ_VERSION) must be greater than latest tag ($LATEST_TAG)."
exit 1
fi
if [ "$PROJ_VERSION" = "$LATEST_VERSION" ]; then
echo "::error::Version ($PROJ_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" != "$PROJ_VERSION" ]; then
echo "::error::CHANGELOG top version ($CHANGELOG_HEAD) does not match Directory.Build.props Version ($PROJ_VERSION)."
exit 1
fi
echo "Version bump check passed: Directory.Build.props and CHANGELOG at $PROJ_VERSION (latest tag: $LATEST_TAG)."
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
| **Test (integration)** | `dotnet test Contentstack.Management.Core.Tests/Contentstack.Management.Core.Tests.csproj` — requires local `appsettings.json` with credentials (see [`skills/testing/SKILL.md`](skills/testing/SKILL.md)). |
| **Pack (release)** | `dotnet pack -c Release -o out` (as in [`.github/workflows/nuget-publish.yml`](.github/workflows/nuget-publish.yml)). |

**CI:** [`.github/workflows/unit-test.yml`](.github/workflows/unit-test.yml) (unit tests on PR/push). **Branches:** PRs normally target **`development`**; **`main`** is for **hotfixes**. PRs **into `main`** must come from **`staging`** per [`.github/workflows/check-branch.yml`](.github/workflows/check-branch.yml).
**CI:** [`.github/workflows/unit-test.yml`](.github/workflows/unit-test.yml) (unit tests on PR/push). **Branches:** feature work merges to **`development`**; **release PRs** are **`development` → `main`** (no `staging`). After `main` advances, [`.github/workflows/back-merge-pr.yml`](.github/workflows/back-merge-pr.yml) can open **`main` → `development`**. **Releases:** create a **GitHub Release** to run [`.github/workflows/nuget-publish.yml`](.github/workflows/nuget-publish.yml) (`release: created`). [`.github/workflows/check-version-bump.yml`](.github/workflows/check-version-bump.yml) enforces version + `CHANGELOG.md` on relevant PRs.

## Where the documentation lives: skills

Expand Down
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>

<IsPackable>false</IsPackable>
<ReleaseVersion>$(Version)</ReleaseVersion>

<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../CSManagementSDK.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.8.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.8.2" />
<PackageReference Include="coverlet.collector" Version="6.0.4"><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.2" />
<PackageReference Include="AutoFixture" Version="4.18.1" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.18.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>

<ItemGroup>
<Folder Include="Helpers\" />
<Folder Include="IntegrationTest\" />
<Folder Include="Model\" />
<Folder Include="Mock\" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Mock\*.json" />
</ItemGroup>

<ItemGroup>
<Content Include="appSettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<ItemGroup>
<None Remove="Microsoft.AspNetCore.Http" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Contentstack.Management.Core\contentstack.management.core.csproj" />
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<IsPackable>false</IsPackable>
<ReleaseVersion>$(Version)</ReleaseVersion>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../CSManagementSDK.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.8.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.8.2" />
<PackageReference Include="coverlet.collector" Version="6.0.4"><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.2" />
<PackageReference Include="AutoFixture" Version="4.18.1" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.18.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="Helpers\" />
<Folder Include="IntegrationTest\" />
<Folder Include="Model\" />
<Folder Include="Mock\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Mock\*.json" />
</ItemGroup>
<ItemGroup>
<Content Include="appSettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Remove="Microsoft.AspNetCore.Http" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Contentstack.Management.Core\contentstack.management.core.csproj" />
</ItemGroup>
</Project>
Loading
Loading