Skip to content

Commit 43725a5

Browse files
authored
Refactor update-codeql workflow to create a PR, not a release (#316)
* Replace update-codeql to create PR not release - Replaces the 4-job release pipeline with a 2-job PR-creation approach. - Also adds a concurrency guard to release.yml to prevent racing releases for the same version. * Replace update-codeql to create PR not release - Replaces the 4-job release pipeline with a 2-job PR-creation approach. - Also adds a concurrency guard to release.yml to prevent racing releases for the same version. * Add upgrade-packs.sh script & address PR review This commit: - adds the scripts/upgrade-packs.sh script to provide a standard script for a common repo maintenance task; - updates the update-codeql.yml actions workflow in order to: - address PR review comments; - run the new upgrade-packs.sh script as a step in the workflow.
1 parent c7a14a8 commit 43725a5

File tree

3 files changed

+234
-68
lines changed

3 files changed

+234
-68
lines changed

.github/workflows/release.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ on:
2424
permissions:
2525
contents: read
2626

27+
concurrency:
28+
group: release-${{ github.event.inputs.version || github.ref_name }}
29+
cancel-in-progress: true
30+
2731
jobs:
2832
# ─────────────────────────────────────────────────────────────────────────────
2933
# Step 1: Determine the release version

.github/workflows/update-codeql.yml

Lines changed: 104 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ jobs:
1515
#
1616
# Compares the current CodeQL CLI version in qlt.conf.json against the latest
1717
# release from github/codeql-cli-binaries. If a newer version is available,
18-
# downstream jobs orchestrate a full release using the same child workflows
19-
# as release.yml, guarded by environment approval gates.
18+
# downstream jobs orchestrate the update and PR creation.
2019
# ─────────────────────────────────────────────────────────────────────────────
2120
detect-update:
2221
name: Detect CodeQL CLI Update
@@ -38,8 +37,21 @@ jobs:
3837
GH_TOKEN: ${{ github.token }}
3938
run: |
4039
echo "Checking latest CodeQL CLI version..."
40+
41+
# Read current version from qlt.conf.json
4142
current_version=$(jq -r .CodeQLCLI qlt.conf.json)
43+
44+
# Get latest release from codeql-cli-binaries
4245
latest_tag=$(gh release list --repo github/codeql-cli-binaries --json 'tagName,isLatest' --jq '.[] | select(.isLatest == true) | .tagName')
46+
47+
# Validate that we found a latest release
48+
if [ -z "${latest_tag}" ]; then
49+
echo "❌ Error: Could not determine latest CodeQL CLI version from github/codeql-cli-binaries" >&2
50+
echo "No release marked as 'latest' was found. This may indicate an API issue or repository change." >&2
51+
echo "update_needed=false" >> $GITHUB_OUTPUT
52+
exit 1
53+
fi
54+
4355
latest_clean="${latest_tag#v}"
4456
4557
echo "Current CodeQL CLI version: ${current_version}"
@@ -63,91 +75,115 @@ jobs:
6375
if [ "${{ steps.check-version.outputs.update_needed }}" == "true" ]; then
6476
echo "✅ Update available: ${{ steps.check-version.outputs.current_version }} → ${{ steps.check-version.outputs.latest_version }}" >> $GITHUB_STEP_SUMMARY
6577
echo "" >> $GITHUB_STEP_SUMMARY
66-
echo "Initiating release pipeline for \`v${{ steps.check-version.outputs.latest_version }}\`..." >> $GITHUB_STEP_SUMMARY
78+
echo "Initiating update pipeline for \`${{ steps.check-version.outputs.version }}\`..." >> $GITHUB_STEP_SUMMARY
6779
else
68-
echo "ℹ️ CodeQL CLI is already up-to-date. No release needed." >> $GITHUB_STEP_SUMMARY
80+
echo "ℹ️ CodeQL CLI is already up-to-date. No changes needed." >> $GITHUB_STEP_SUMMARY
6981
fi
7082
7183
# ─────────────────────────────────────────────────────────────────────────────
72-
# Step 2: Create release tag
84+
# Step 2: Update version, test, and create PR
7385
#
74-
# Calls the same release-tag workflow used by release.yml. This ensures the
75-
# version update, CodeQL installation, pack lock upgrade, unit tests, and tag
76-
# creation all follow the same validated process.
86+
# Updates all version-bearing files (qlt.conf.json, qlpack.yml files),
87+
# installs CodeQL, upgrades pack lock files, compiles CDS files, runs unit
88+
# tests, and creates a pull request with the changes.
7789
#
78-
# The release-tag environment approval gate provides human-in-the-loop review
79-
# before any changes are committed.
90+
# This does NOT trigger the release pipeline. Merging the PR and creating a
91+
# release tag is a separate, human-initiated step via release.yml.
8092
# ─────────────────────────────────────────────────────────────────────────────
81-
ensure-tag:
82-
name: Ensure Release Tag
93+
create-pr:
94+
name: Create Update Pull Request
8395
needs: detect-update
8496
if: needs.detect-update.outputs.update_needed == 'true'
85-
permissions:
86-
contents: write
87-
uses: ./.github/workflows/release-tag.yml
88-
with:
89-
version: ${{ needs.detect-update.outputs.version }}
90-
91-
# ─────────────────────────────────────────────────────────────────────────────
92-
# Step 3: Publish and bundle CodeQL packs
93-
#
94-
# Calls the same release-codeql workflow used by release.yml. Publishes packs
95-
# to GHCR and bundles them as artifacts for the GitHub Release.
96-
# ─────────────────────────────────────────────────────────────────────────────
97-
publish-codeql:
98-
name: Publish CodeQL Packs
99-
needs: [detect-update, ensure-tag]
100-
if: needs.detect-update.outputs.update_needed == 'true'
101-
permissions:
102-
contents: read
103-
packages: write
104-
uses: ./.github/workflows/release-codeql.yml
105-
with:
106-
publish_codeql_packs: true
107-
version: ${{ needs.detect-update.outputs.version }}
108-
109-
# ─────────────────────────────────────────────────────────────────────────────
110-
# Step 4: Create GitHub Release
111-
#
112-
# Downloads the CodeQL pack bundles and creates the GitHub Release with
113-
# auto-generated release notes and attached pack artifacts.
114-
# ─────────────────────────────────────────────────────────────────────────────
115-
create-release:
116-
name: Create GitHub Release
117-
needs: [detect-update, ensure-tag, publish-codeql]
118-
if: >-
119-
always() && !failure() && !cancelled()
120-
&& needs.detect-update.outputs.update_needed == 'true'
12197
runs-on: ubuntu-latest
12298

12399
permissions:
124100
contents: write
101+
pull-requests: write
125102

126103
steps:
127-
- name: Release - Download CodeQL pack artifacts
128-
uses: actions/download-artifact@v7
129-
with:
130-
name: codeql-pack-bundles-${{ needs.detect-update.outputs.version }}
131-
path: dist-packs
104+
- name: Update - Checkout repository
105+
uses: actions/checkout@v6
106+
107+
- name: Update - Update version in all files
108+
run: |
109+
LATEST="${{ needs.detect-update.outputs.latest_version }}"
110+
echo "Updating all version-bearing files to ${LATEST}..."
111+
./scripts/update-release-version.sh "${LATEST}"
132112
133-
- name: Release - Create GitHub Release
134-
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
113+
- name: Update - Install CodeQL via GitHub CLI
114+
env:
115+
GH_TOKEN: ${{ github.token }}
116+
shell: bash
117+
run: |
118+
CODEQL_VERSION="${{ needs.detect-update.outputs.latest_version }}"
119+
echo "Installing CodeQL CLI ${CODEQL_VERSION} via gh-codeql..."
120+
gh extension install github/gh-codeql
121+
gh codeql set-version "${CODEQL_VERSION}"
122+
STUB_DIR="$HOME/.local/bin"
123+
mkdir -p "${STUB_DIR}"
124+
gh codeql install-stub "${STUB_DIR}/"
125+
echo "${STUB_DIR}" >> "$GITHUB_PATH"
126+
export PATH="${STUB_DIR}:${PATH}"
127+
echo "CodeQL version: $(codeql version --format=terse)"
128+
129+
- name: Update - Upgrade CodeQL pack lock files
130+
run: ./scripts/upgrade-packs.sh
131+
132+
- name: Update - Setup Node.js for CDS compilation
133+
uses: actions/setup-node@v6
135134
with:
136-
files: |
137-
dist-packs/*.tar.gz
138-
generate_release_notes: true
139-
tag_name: ${{ needs.detect-update.outputs.version }}
135+
node-version: '20'
136+
cache: 'npm'
137+
cache-dependency-path: 'extractors/cds/tools/package-lock.json'
140138

141-
- name: Release - Summary
139+
- name: Update - Compile CAP CDS files
140+
run: ./extractors/cds/tools/workflow/cds-compilation-for-actions.sh
141+
142+
- name: Update - Run CodeQL unit tests
143+
env:
144+
LGTM_INDEX_XML_MODE: all
145+
LGTM_INDEX_FILETYPES: ".json:JSON\n.cds:JSON"
146+
shell: bash
147+
run: |
148+
echo "Running CodeQL unit tests to validate update..."
149+
codeql test run \
150+
--threads=0 \
151+
--strict-test-discovery \
152+
--additional-packs="${GITHUB_WORKSPACE}" \
153+
-- javascript/
154+
155+
- name: Update - Create Pull Request
156+
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
157+
with:
158+
title: 'Upgrade CodeQL CLI dependency to ${{ needs.detect-update.outputs.version }}'
159+
body: |
160+
This PR upgrades the CodeQL CLI version to ${{ needs.detect-update.outputs.version }}.
161+
162+
**Changes made:**
163+
- Updated `qlt.conf.json` (CodeQLCLI, CodeQLStandardLibrary, CodeQLCLIBundle) to `${{ needs.detect-update.outputs.latest_version }}`
164+
- Updated all version-bearing qlpack.yml files to `${{ needs.detect-update.outputs.latest_version }}`
165+
- Upgraded CodeQL pack lock files
166+
- Compiled CAP CDS files
167+
- CodeQL unit tests passed ✅
168+
169+
**To complete the release**, merge this PR and then trigger the release workflow
170+
via `workflow_dispatch` on `release.yml` with version `${{ needs.detect-update.outputs.version }}`.
171+
commit-message: 'Upgrade CodeQL CLI dependency to ${{ needs.detect-update.outputs.version }}'
172+
delete-branch: true
173+
branch: 'codeql/upgrade-to-${{ needs.detect-update.outputs.version }}'
174+
175+
- name: Update - Summary
142176
run: |
143177
VERSION="${{ needs.detect-update.outputs.version }}"
144-
RELEASE_NAME="${{ needs.detect-update.outputs.latest_version }}"
145-
echo "## Automated Release Summary" >> $GITHUB_STEP_SUMMARY
178+
CURRENT="${{ needs.detect-update.outputs.current_version }}"
179+
LATEST="${{ needs.detect-update.outputs.latest_version }}"
180+
echo "## CodeQL CLI Update Summary" >> $GITHUB_STEP_SUMMARY
181+
echo "" >> $GITHUB_STEP_SUMMARY
182+
echo "Triggered by CodeQL CLI update: ${CURRENT} → ${LATEST}" >> $GITHUB_STEP_SUMMARY
146183
echo "" >> $GITHUB_STEP_SUMMARY
147-
echo "Triggered by CodeQL CLI update: ${{ needs.detect-update.outputs.current_version }} → ${RELEASE_NAME}" >> $GITHUB_STEP_SUMMARY
184+
echo "| Property | Old Value | New Value |" >> $GITHUB_STEP_SUMMARY
185+
echo "| -------- | --------- | --------- |" >> $GITHUB_STEP_SUMMARY
186+
echo "| qlt.conf.json CodeQLCLI | ${CURRENT} | ${LATEST} |" >> $GITHUB_STEP_SUMMARY
187+
echo "| qlpack.yml versions | ${CURRENT} | ${LATEST} |" >> $GITHUB_STEP_SUMMARY
148188
echo "" >> $GITHUB_STEP_SUMMARY
149-
echo "| Step | Status |" >> $GITHUB_STEP_SUMMARY
150-
echo "| ---- | ------ |" >> $GITHUB_STEP_SUMMARY
151-
echo "| Tag | ✅ ${VERSION} |" >> $GITHUB_STEP_SUMMARY
152-
echo "| CodeQL pack publish | ✅ Published to GHCR |" >> $GITHUB_STEP_SUMMARY
153-
echo "| GitHub Release | ✅ Created |" >> $GITHUB_STEP_SUMMARY
189+
echo "A pull request has been created with these changes." >> $GITHUB_STEP_SUMMARY

scripts/upgrade-packs.sh

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
## upgrade-packs.sh
5+
## Upgrade CodeQL pack dependencies for packs in the codeql-sap-js repository.
6+
##
7+
## This script upgrades lock files for both source and test packs, installing
8+
## the latest compatible version of each dependency (ignoring existing lock files).
9+
##
10+
## Usage:
11+
## ./scripts/upgrade-packs.sh
12+
## ./scripts/upgrade-packs.sh --framework cap
13+
## ./scripts/upgrade-packs.sh --framework ui5
14+
15+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16+
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
17+
18+
FRAMEWORK=""
19+
20+
usage() {
21+
cat <<EOF
22+
Usage: $0 [OPTIONS]
23+
24+
Upgrade CodeQL pack dependencies for all packs in the repository.
25+
26+
OPTIONS:
27+
--framework <name> Upgrade packs only for the specified framework
28+
Valid values: cap, heuristic-models, ui5, ui5-webcomponents, xsjs
29+
-h, --help Show this help message
30+
31+
By default, the script upgrades packs for all frameworks.
32+
EOF
33+
}
34+
35+
while [[ $# -gt 0 ]]; do
36+
case $1 in
37+
--framework)
38+
if [[ $# -lt 2 || "${2-}" == -* ]]; then
39+
echo "Error: --framework requires a value" >&2
40+
usage >&2
41+
exit 1
42+
fi
43+
FRAMEWORK="$2"
44+
shift 2
45+
;;
46+
-h|--help)
47+
usage
48+
exit 0
49+
;;
50+
*)
51+
echo "Error: Unknown option $1" >&2
52+
usage >&2
53+
exit 1
54+
;;
55+
esac
56+
done
57+
58+
## Validate framework if provided
59+
VALID_FRAMEWORKS=("cap" "heuristic-models" "ui5" "ui5-webcomponents" "xsjs")
60+
if [[ -n "${FRAMEWORK}" ]]; then
61+
FRAMEWORK_VALID=false
62+
for valid_fw in "${VALID_FRAMEWORKS[@]}"; do
63+
if [[ "${FRAMEWORK}" == "${valid_fw}" ]]; then
64+
FRAMEWORK_VALID=true
65+
break
66+
fi
67+
done
68+
69+
if [[ "${FRAMEWORK_VALID}" == false ]]; then
70+
echo "Error: Invalid framework '${FRAMEWORK}'" >&2
71+
echo "Valid frameworks: ${VALID_FRAMEWORKS[*]}" >&2
72+
exit 1
73+
fi
74+
fi
75+
76+
cd "${REPO_ROOT}"
77+
78+
## Upgrade a single pack given its qlpack.yml directory
79+
upgrade_pack() {
80+
local pack_dir="$1"
81+
if [[ -d "${pack_dir}" ]]; then
82+
echo "INFO: Running 'codeql pack upgrade' for '${pack_dir}'..."
83+
codeql pack upgrade -- "${pack_dir}"
84+
else
85+
echo "WARNING: Directory '${pack_dir}' not found, skipping" >&2
86+
fi
87+
}
88+
89+
## Upgrade packs for a framework (all subdirectories that contain qlpack.yml)
90+
upgrade_framework() {
91+
local framework_path="$1"
92+
echo "Upgrading packs for: ${framework_path}"
93+
94+
# Find all qlpack.yml files under this framework and upgrade their packs
95+
find "${REPO_ROOT}/${framework_path}" -name "qlpack.yml" -type f | sort | while read -r qlpack_file; do
96+
local pack_dir
97+
pack_dir=$(dirname "${qlpack_file}")
98+
# Use relative path for cleaner output
99+
local rel_path="${pack_dir#${REPO_ROOT}/}"
100+
upgrade_pack "${rel_path}"
101+
done
102+
}
103+
104+
if [[ -n "${FRAMEWORK}" ]]; then
105+
case "${FRAMEWORK}" in
106+
heuristic-models)
107+
upgrade_framework "javascript/heuristic-models"
108+
;;
109+
ui5-webcomponents)
110+
upgrade_framework "javascript/frameworks/ui5-webcomponents"
111+
;;
112+
*)
113+
upgrade_framework "javascript/frameworks/${FRAMEWORK}"
114+
;;
115+
esac
116+
else
117+
echo "Upgrading packs for all frameworks..."
118+
upgrade_framework "javascript/frameworks/cap"
119+
upgrade_framework "javascript/frameworks/ui5"
120+
upgrade_framework "javascript/frameworks/ui5-webcomponents"
121+
upgrade_framework "javascript/frameworks/xsjs"
122+
upgrade_framework "javascript/heuristic-models"
123+
fi
124+
125+
echo ""
126+
echo "✅ All CodeQL pack lock files upgraded successfully."

0 commit comments

Comments
 (0)