Skip to content

Commit dc6a6d8

Browse files
authored
Merge pull request #143 from contentstack/fix/DX-6183
chore: migrate java repo to GitHub Release–based publish flow with strict version gating
2 parents ee5986b + 03d9889 commit dc6a6d8

9 files changed

Lines changed: 171 additions & 35 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Opens a PR from master → development after changes land on master (back-merge).
2+
#
3+
# Org/repo Settings → Actions → General → Workflow permissions: read and write
4+
# (so GITHUB_TOKEN can create pull requests). Or use a PAT in secret GH_TOKEN.
5+
6+
name: Back-merge master to development
7+
8+
on:
9+
push:
10+
branches: [master]
11+
workflow_dispatch:
12+
13+
permissions:
14+
contents: read
15+
pull-requests: write
16+
17+
jobs:
18+
open-back-merge-pr:
19+
runs-on: ubuntu-latest
20+
steps:
21+
- name: Checkout
22+
uses: actions/checkout@v4
23+
with:
24+
fetch-depth: 0
25+
26+
- name: Open back-merge PR if needed
27+
env:
28+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
29+
run: |
30+
set -euo pipefail
31+
git fetch origin development master
32+
33+
MASTER_SHA=$(git rev-parse origin/master)
34+
DEV_SHA=$(git rev-parse origin/development)
35+
36+
if [ "$MASTER_SHA" = "$DEV_SHA" ]; then
37+
echo "master and development are at the same commit; nothing to back-merge."
38+
exit 0
39+
fi
40+
41+
EXISTING=$(gh pr list --repo "${{ github.repository }}" \
42+
--base development \
43+
--head master \
44+
--state open \
45+
--json number \
46+
--jq 'length')
47+
48+
if [ "$EXISTING" -gt 0 ]; then
49+
echo "An open PR from master to development already exists; skipping."
50+
exit 0
51+
fi
52+
53+
gh pr create --repo "${{ github.repository }}" \
54+
--base development \
55+
--head master \
56+
--title "chore: back-merge master into development" \
57+
--body "Automated back-merge after changes landed on \`master\`. Review and merge to keep \`development\` in sync."
58+
59+
echo "Created back-merge PR master → development."

.github/workflows/check-branch.yml

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Runs only when production code under src/main/ changes. Version must be > latest v* tag
2+
# (not compared to the base branch, so rebases onto an already-bumped main still pass when tag requires a new release).
3+
4+
name: Check Version Bump
5+
6+
on:
7+
pull_request:
8+
9+
jobs:
10+
check-version-bump:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
with:
15+
fetch-depth: 0
16+
- name: Validate version and changelog updates
17+
shell: bash
18+
run: |
19+
set -euo pipefail
20+
21+
VERSION_FILE="pom.xml"
22+
CHANGELOG_FILE="CHANGELOG.md"
23+
BASE_SHA="${{ github.event.pull_request.base.sha }}"
24+
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
25+
26+
mapfile -t CHANGED_FILES < <(git diff --name-only "$BASE_SHA" "$HEAD_SHA")
27+
if [ "${#CHANGED_FILES[@]}" -eq 0 ]; then
28+
echo "No changed files detected."
29+
exit 0
30+
fi
31+
32+
is_production_source_change() {
33+
local f="$1"
34+
[[ "$f" == src/main/* ]]
35+
}
36+
37+
has_source_changes=false
38+
for file in "${CHANGED_FILES[@]}"; do
39+
if is_production_source_change "$file"; then
40+
has_source_changes=true
41+
break
42+
fi
43+
done
44+
45+
if [ "$has_source_changes" = false ]; then
46+
echo "Skipping: no src/main/ production code changes."
47+
exit 0
48+
fi
49+
50+
changed_file() {
51+
local target="$1"
52+
for file in "${CHANGED_FILES[@]}"; do
53+
if [ "$file" = "$target" ]; then
54+
return 0
55+
fi
56+
done
57+
return 1
58+
}
59+
60+
changed_file "$VERSION_FILE" || { echo "Version bump required in $VERSION_FILE."; exit 1; }
61+
changed_file "$CHANGELOG_FILE" || { echo "Matching changelog update required in $CHANGELOG_FILE."; exit 1; }
62+
63+
extract_version() {
64+
python3 -c 'import sys,xml.etree.ElementTree as ET;r=ET.fromstring(sys.stdin.read());ns={"m":r.tag.split("}")[0].strip("{")} if r.tag.startswith("{") else None;n=(r.find("m:version",ns) if ns else r.find("version"));print((n.text or "").strip() if n is not None else "")'
65+
}
66+
67+
head_version=$(extract_version < "$VERSION_FILE")
68+
# Changelog uses "## Date" sections with versions on "#### vX.Y.Z" lines; support that and legacy "## vX.Y.Z".
69+
CHANGELOG_HEAD=$(
70+
sed -nE 's/^####[[:space:]]+v?([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' "$CHANGELOG_FILE" | head -1
71+
)
72+
if [ -z "$CHANGELOG_HEAD" ]; then
73+
CHANGELOG_HEAD=$(sed -nE 's/^##[[:space:]]+v?([0-9]+\.[0-9]+\.[0-9]+).*/\1/p' "$CHANGELOG_FILE" | head -1)
74+
fi
75+
76+
[ -n "$CHANGELOG_HEAD" ] || { echo "::error::Could not find a version in $CHANGELOG_FILE (expected '#### vX.Y.Z' under a date section or legacy '## vX.Y.Z')."; exit 1; }
77+
[ "$CHANGELOG_HEAD" = "$head_version" ] || { echo "::error::$CHANGELOG_FILE top release version ($CHANGELOG_HEAD) does not match project version ($head_version)."; exit 1; }
78+
79+
latest_tag=$(git tag --list 'v*' --sort=-version:refname | sed -n '1p')
80+
latest_version="${latest_tag#v}"
81+
[ -n "$latest_version" ] || latest_version="0.0.0"
82+
83+
version_gt() {
84+
python3 -c 'import sys;v=lambda s:[int(x) if x.isdigit() else 0 for x in (s.strip().lstrip("v").split("-",1)[0].split("+",1)[0].split(".")+["0","0","0"])[:3]];print("true" if v(sys.argv[1])>v(sys.argv[2]) else "false")' "$1" "$2"
85+
}
86+
87+
[ "$(version_gt "$head_version" "$latest_version")" = "true" ] || { echo "Version must be greater than latest tag version ($latest_version). Found $head_version."; exit 1; }

.github/workflows/maven-publish.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ on:
44
types: [created]
55
jobs:
66
publish-maven:
7+
if: ${{ startsWith(github.event.release.tag_name, 'v') && !github.event.release.draft }}
78
runs-on: ubuntu-latest
89
permissions:
910
contents: read
1011
packages: write
1112
steps:
1213
- uses: actions/checkout@v3
14+
with:
15+
ref: ${{ github.event.release.tag_name }}
1316
- name: Set up Maven Central Repository
1417
uses: actions/setup-java@v3
1518
with:
@@ -27,17 +30,20 @@ jobs:
2730
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
2831
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
2932
publish-github:
33+
if: ${{ startsWith(github.event.release.tag_name, 'v') && !github.event.release.draft }}
3034
runs-on: ubuntu-latest
3135
steps:
3236
- uses: actions/checkout@v3
37+
with:
38+
ref: ${{ github.event.release.tag_name }}
3339
- name: Set up Java for publishing to GitHub Packages
3440
uses: actions/setup-java@v3
3541
with:
3642
java-version: '17'
3743
distribution: 'adopt'
3844
server-id: github
3945
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
40-
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
46+
gpg-passphrase: GPG_PASSPHRASE
4147
- name: Set up Maven settings for Central and GitHub
4248
run: |
4349
mkdir -p $HOME/.m2
@@ -58,4 +64,4 @@ jobs:
5864
- name: Publish to GitHub Packages
5965
run: mvn --batch-mode -Dgpg.passphrase=${{ secrets.GPG_PASSPHRASE }} deploy
6066
env:
61-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
67+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
| Single test class | `mvn test -Dtest=UtilTests` |
3434
| Javadoc | `mvn javadoc:javadoc` |
3535
| Sample (after `mvn install` with skips if needed) | `mvn -f sample/pom.xml compile` |
36-
| **CI** | Java **17** publish: `.github/workflows/maven-publish.yml` · SCA: `.github/workflows/sca-scan.yml` · branch rules: `.github/workflows/check-branch.yml` |
36+
| **CI** | Java **17** publish: `.github/workflows/maven-publish.yml` (GitHub **Release** for tag `v*`, draft releases skipped) · SCA: `.github/workflows/sca-scan.yml` · back-merge automation: `.github/workflows/back-merge-pr.yml` |
3737

3838
## Where the documentation lives: skills
3939

Changelog.md renamed to CHANGELOG.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
# Changelog
1+
# CHANGELOG
22

33
A brief description of what changes project contains
44

5+
## Apr 30, 2026
6+
7+
#### v1.5.1
8+
9+
- Fix: Upgraded `org.springframework:spring-web` to 7.0.7 to address Snyk-reported vulnerabilities in Spring Framework (including transitive `spring-core`)
10+
511
## Apr 20, 2026
612

713
#### v1.5.0
814

9-
- Enhancement: Live Preview Editable tags
15+
- Enhancement: Live Preview Editable tags
1016

1117
## Mar 23, 2026
1218

@@ -36,7 +42,7 @@ A brief description of what changes project contains
3642

3743
#### v1.2.11
3844

39-
- Fix: ignore td/th in case of attrs has void:true
45+
- Fix: ignore td/th in case of attrs has void:true
4046

4147
## May 14, 2024
4248

@@ -48,7 +54,7 @@ A brief description of what changes project contains
4854

4955
#### v1.2.9
5056

51-
- Fixed vulnerability issue related to strAttrs and children.
57+
- Fixed vulnerability issue related to strAttrs and children.
5258

5359
## April 23, 2024
5460

@@ -136,4 +142,3 @@ A brief description of what changes project contains
136142
## Support
137143

138144
- For support, email fake@fake.com or join our Slack channel.
139-

pom.xml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>com.contentstack.sdk</groupId>
66
<artifactId>utils</artifactId>
7-
<version>1.5.0</version>
7+
<version>1.5.1</version>
88
<packaging>jar</packaging>
99
<name>Contentstack-utils</name>
1010
<description>Java Utils SDK for Contentstack Content Delivery API, Contentstack is a headless CMS</description>
@@ -28,7 +28,7 @@
2828
<maven-release-plugin.version>2.5.3</maven-release-plugin.version>
2929
<validation-version>2.0.1.Final</validation-version>
3030
<json-version>20251224</json-version>
31-
<spring-web-version>7.0.6</spring-web-version>
31+
<spring-web-version>7.0.7</spring-web-version>
3232
<org.apache.commons-text>1.15.0</org.apache.commons-text>
3333
</properties>
3434

@@ -212,8 +212,7 @@
212212
<use>false</use>
213213
<source>17</source>
214214
<links>
215-
<link>http://docs.oracle.com/javase/8/docs/api/</link>
216-
<link>http://docs.oracle.com/javase/8/docs/api/</link>
215+
<link>https://docs.oracle.com/en/java/javase/17/docs/api/</link>
217216
</links>
218217
<doclint>none</doclint>
219218
</configuration>

skills/code-review/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ description: PR checklist and optional Blocker/Major/Minor — use when reviewin
1616
### API design and stability
1717

1818
- [ ] **Public API:** New or changed methods on `Utils`, `GQL`, `DefaultOption`, or `interfaces` are necessary, Javadoc’d, and safe for `com.contentstack.sdk:utils` consumers.
19-
- [ ] **Backward compatibility:** Breaking changes only with major version / **`Changelog.md`** plan.
19+
- [ ] **Backward compatibility:** Breaking changes only with major version / **`CHANGELOG.md`** plan.
2020
- [ ] **Naming:** Consistent with existing Utils and RTE/embedded terminology.
2121

2222
### Error handling and robustness

skills/dev-workflow/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ description: Branches, CI, build and test commands, PR expectations, optional TD
1515

1616
### Branches
1717

18-
- Default integration for PRs is often **`staging`**; merging into **`master`** may be restricted (see `.github/workflows/check-branch.yml`).
18+
- Feature/fix PRs should target **`development`**. Release PRs are raised directly from **`development`** to **`master`**.
1919
- Feature/fix branches often use ticket-style names (e.g. `fix/DX-5734`).
2020

2121
### Running tests and builds
@@ -28,7 +28,7 @@ description: Branches, CI, build and test commands, PR expectations, optional TD
2828
### Pull requests
2929

3030
- Describe the change; link issues/tickets when applicable.
31-
- Keep public API backward-compatible unless releasing a breaking version; update **`Changelog.md`** for user-visible behavior.
31+
- Keep public API backward-compatible unless releasing a breaking version; update **`CHANGELOG.md`** for user-visible behavior.
3232
- Use **`skills/code-review/SKILL.md`** as the review checklist.
3333

3434
### Optional: TDD

0 commit comments

Comments
 (0)