Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
05b0d76
Implement changelog generation script and update Gradle build configu…
cx-amol-mane Feb 27, 2026
5f4b4e2
Update GitHub Actions workflow to specify test task for Checkmarx plugin
cx-amol-mane Feb 27, 2026
3060792
Update test command in GitHub Actions workflow for Checkmarx plugin
cx-amol-mane Feb 27, 2026
8319b3c
Refactor changelog script to improve hash extraction method
cx-amol-mane Feb 27, 2026
6b86489
Refactor changelog generation and update release workflow
cx-amol-mane Feb 27, 2026
25f7837
Enhance changelog generation by stripping leading whitespace and bull…
cx-amol-mane Feb 27, 2026
3604b32
Enhance changelog formatting and update release name in workflow
cx-amol-mane Feb 27, 2026
5533bce
Refactor release workflow to conditionally generate changelogs for pl…
cx-amol-mane Feb 28, 2026
e9915ec
Refactor changelog script and release workflow to remove unnecessary …
cx-amol-mane Feb 28, 2026
3092de5
Update release workflow to dynamically set product name based on rele…
cx-amol-mane Feb 28, 2026
51a62fd
Add skip_tests input to release workflow for optional integration tes…
cx-amol-mane Feb 28, 2026
8149b5c
Update release workflow conditions to ensure successful integration t…
cx-amol-mane Feb 28, 2026
4365824
Enhance nightly and release workflows to include version outputs for …
cx-amol-mane Mar 2, 2026
6695236
Update nightly workflow to use feature branch for release pipeline
cx-amol-mane Mar 2, 2026
f49b879
Update nightly workflow to use main branch for release pipeline
cx-amol-mane Mar 2, 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
231 changes: 231 additions & 0 deletions .github/scripts/generateChangelog.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
#!/usr/bin/env bash
set -euo pipefail

# ---------------------------------------------------------------------------
# Generate changelog for a specific plugin using git log filtered by path.
#
# Mirrors the VS Code extension's generateChangelog.js for the JetBrains
# multi-plugin monorepo.
#
# Usage:
# ./generateChangelog.sh --plugin checkmarx --version 2.3.4 --repo Checkmarx/ast-jetbrains-plugin
# ./generateChangelog.sh --plugin devassist --version 1.0.0 --repo Checkmarx/ast-jetbrains-plugin
#
# Outputs:
# Structured release body section on stdout between RELEASE_BODY_START / RELEASE_BODY_END
# ---------------------------------------------------------------------------

PLUGIN=""
VERSION=""
REPO=""

while [[ $# -gt 0 ]]; do
case "$1" in
--plugin) PLUGIN="$2"; shift 2 ;;
--version) VERSION="$2"; shift 2 ;;
--repo) REPO="$2"; shift 2 ;;
*) echo "Unknown arg: $1" >&2; exit 1 ;;
esac
done

if [[ -z "$PLUGIN" || -z "$VERSION" || -z "$REPO" ]]; then
echo "Usage: $0 --plugin checkmarx|devassist --version X.Y.Z --repo owner/repo" >&2
exit 1
fi

case "$PLUGIN" in
checkmarx)
DISPLAY_NAME="Checkmarx (AST)"
GIT_PATHS=("plugin-checkmarx-ast/" "common-lib/")
;;
devassist)
DISPLAY_NAME="DevAssist"
GIT_PATHS=("plugin-checkmarx-devassist/" "devassist-lib/" "common-lib/")
;;
*)
echo "--plugin must be 'checkmarx' or 'devassist'" >&2
exit 1
;;
esac

REPO_URL="https://github.com/${REPO}"

# ---------------------------------------------------------------------------
# Find last stable tag (plain version tags like 2.3.3, no suffix)
# Tags follow the JetBrains convention: plain numbers, no v prefix
# ---------------------------------------------------------------------------
find_last_stable_tag() {
local all_tags
all_tags=$(git tag --sort=-creatordate 2>/dev/null || true)

if [[ -z "$all_tags" ]]; then
echo ""
return
fi

while IFS= read -r tag; do
# Match plain version tags (e.g. 2.3.3) -- no suffix like -nightly
if [[ "$tag" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "$tag"
return
fi
done <<< "$all_tags"

# Fallback: check v-prefixed tags (legacy)
while IFS= read -r tag; do
if [[ "$tag" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "$tag"
return
fi
done <<< "$all_tags"

echo ""
}

LAST_TAG=$(find_last_stable_tag)
if [[ -n "$LAST_TAG" ]]; then
echo "Found last stable tag: $LAST_TAG" >&2
RANGE="${LAST_TAG}..HEAD"
else
echo "No stable tag found, using full history" >&2
RANGE="HEAD"
fi

# ---------------------------------------------------------------------------
# Patterns to exclude (automation / version bump commits)
# ---------------------------------------------------------------------------
EXCLUDE_REGEX="(update.*version.*automated|bump version|\[create-pull-request\] automated|Merge pull request.*dependabot|^Merge branch)"

# ---------------------------------------------------------------------------
# Collect commits filtered by subproject paths
# ---------------------------------------------------------------------------
RAW_LOG=$(git log ${RANGE} --pretty=format:"%H|||%s|||%an" -- "${GIT_PATHS[@]}" 2>/dev/null || true)

# ---------------------------------------------------------------------------
# Categorize commits by conventional commit patterns
# ---------------------------------------------------------------------------
declare -a FEATURES=()
declare -a FIXES=()
declare -a DOCS=()
declare -a REFACTORS=()
declare -a PERFS=()
declare -a OTHERS=()

if [[ -n "$RAW_LOG" ]]; then
while IFS= read -r line; do
HASH=$(echo "$line" | awk -F'\\|\\|\\|' '{print $1}')
MSG=$(echo "$line" | awk -F'\\|\\|\\|' '{print $2}')
AUTHOR_NAME=$(echo "$line" | awk -F'\\|\\|\\|' '{print $3}')

# Strip leading whitespace, then leading "* " or "- " from squash/merge commit subjects
MSG=$(echo "$MSG" | sed 's/^[[:space:]]*//' | sed 's/^[*-][[:space:]]*//')

[[ -z "$MSG" ]] && continue

if echo "$MSG" | grep -qiE "$EXCLUDE_REGEX"; then
continue
fi

GH_USER="$AUTHOR_NAME"
if command -v gh &>/dev/null && [[ -n "$HASH" ]]; then
RESOLVED=$(gh api "repos/${REPO}/commits/${HASH}" --template '{{.author.login}}' 2>/dev/null || true)
if [[ -n "$RESOLVED" && "$RESOLVED" != " " ]]; then
GH_USER="$RESOLVED"
else
GH_USER=$(echo "$AUTHOR_NAME" | tr -d ' ')
fi
fi

ENTRY="- ${MSG} by @${GH_USER}"
MSG_LOWER=$(echo "$MSG" | tr '[:upper:]' '[:lower:]')

if echo "$MSG" | grep -qE "^feat(\(.+\))?[:\!]" || echo "$MSG_LOWER" | grep -qiE "\b(add|added|adding|new feature|feature|implement|implemented)\b"; then
FEATURES+=("$ENTRY")
elif echo "$MSG" | grep -qE "^fix(\(.+\))?[:\!]" || echo "$MSG_LOWER" | grep -qiE "\b(fix|fixed|fixing|fixes|resolve|resolved|bug)\b"; then
FIXES+=("$ENTRY")
elif echo "$MSG" | grep -qE "^docs(\(.+\))?[:\!]" || echo "$MSG_LOWER" | grep -qiE "\b(doc|docs|documentation|readme)\b"; then
DOCS+=("$ENTRY")
elif echo "$MSG" | grep -qE "^refactor(\(.+\))?[:\!]" || echo "$MSG_LOWER" | grep -qiE "\b(refactor|refactoring|restructure|reorganize)\b"; then
REFACTORS+=("$ENTRY")
elif echo "$MSG" | grep -qE "^perf(\(.+\))?[:\!]" || echo "$MSG_LOWER" | grep -qiE "\b(perf|performance|optimize|optimized|optimization)\b"; then
PERFS+=("$ENTRY")
else
OTHERS+=("$ENTRY")
fi
done <<< "$RAW_LOG"
fi

# ---------------------------------------------------------------------------
# Build the release body section (write line-by-line for clean markdown)
# ---------------------------------------------------------------------------
emit() { printf '%s\n' "$1"; }

echo "RELEASE_BODY_START"

emit "## ${DISPLAY_NAME}: ${VERSION}"
emit ""
emit "### What's Changed"
emit ""

section_added=false

if [[ ${#FEATURES[@]} -gt 0 ]]; then
emit "#### 🚀 New Features"
emit ""
for e in "${FEATURES[@]}"; do emit "$e"; done
emit ""
section_added=true
fi

if [[ ${#FIXES[@]} -gt 0 ]]; then
emit "#### 🐛 Bug Fixes"
emit ""
for e in "${FIXES[@]}"; do emit "$e"; done
emit ""
section_added=true
fi

if [[ ${#DOCS[@]} -gt 0 ]]; then
emit "#### 📝 Documentation"
emit ""
for e in "${DOCS[@]}"; do emit "$e"; done
emit ""
section_added=true
fi

if [[ ${#REFACTORS[@]} -gt 0 ]]; then
emit "#### ♻️ Refactor"
emit ""
for e in "${REFACTORS[@]}"; do emit "$e"; done
emit ""
section_added=true
fi

if [[ ${#PERFS[@]} -gt 0 ]]; then
emit "#### ⚡ Performance"
emit ""
for e in "${PERFS[@]}"; do emit "$e"; done
emit ""
section_added=true
fi

if [[ ${#OTHERS[@]} -gt 0 ]]; then
emit "#### 🔧 Other Changes"
emit ""
for e in "${OTHERS[@]}"; do emit "$e"; done
emit ""
section_added=true
fi

if [[ "$section_added" == "false" ]]; then
emit "_No changes_"
emit ""
fi

if [[ -n "$LAST_TAG" ]]; then
emit "**Full Changelog**: ${REPO_URL}/compare/${LAST_TAG}...${VERSION}"
else
emit "**Full Changelog**: ${REPO_URL}/releases/tag/${VERSION}"
fi

echo "RELEASE_BODY_END"
21 changes: 15 additions & 6 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,26 @@ jobs:
set_tag:
runs-on: ubuntu-latest
outputs:
tag_name: ${{ steps.tagname.outputs.tag_name }}
tag_version: ${{ steps.tagname.outputs.tag_version }}
ast_version: ${{ steps.tagname.outputs.ast_version }}
devassist_version: ${{ steps.tagname.outputs.devassist_version }}
steps:
- name: Create tagname
run: echo "tag_name=2.0.$(date +%s)" >> "$GITHUB_OUTPUT"
- name: Create version
id: tagname
- name: Print tagname
run: echo "created tag ${{ steps.tagname.outputs.tag_name }}"
run: |
TS=$(date +%s)
echo "tag_version=2.0.${TS}" >> "$GITHUB_OUTPUT"
echo "ast_version=2.0.${TS}" >> "$GITHUB_OUTPUT"
echo "devassist_version=1.0.${TS}" >> "$GITHUB_OUTPUT"
- name: Print version
run: echo "created version ${{ steps.tagname.outputs.tag_version }}"
nightly:
needs: set_tag
uses: Checkmarx/ast-jetbrains-plugin/.github/workflows/release.yml@main
with:
tag: ${{ needs.set_tag.outputs.tag_name }}
tag: ${{ needs.set_tag.outputs.tag_version }}
ast_version: ${{ needs.set_tag.outputs.ast_version }}
devassist_version: ${{ needs.set_tag.outputs.devassist_version }}
releaseType: "checkmarx"
rchannels: "nightly"
secrets: inherit
Loading
Loading