| name | release-sync |
| description | Audit and update Argus external distribution surfaces (Spring Boot starter, Helm chart, Docker, install scripts, Homebrew Formula, SDKMAN, GitHub Actions, action.yml) against gradle.properties and known-good upstream versions. Detects version drift, floating image tags, deprecated K8s APIs, and outdated dependencies. Use before a release, or when the user asks to "sync release", "update distributions", "check outdated deps", "verify external integrations". |
| argument-hint | [--check] [--fix] |
release-sync
Keep every Argus distribution channel aligned with the project version and free of stale dependencies.
When to use
- Before tagging a release
- After bumping
argusVersion in gradle.properties
- Periodic outdated-dependency sweep (Netty CVEs, Spring Boot, Micrometer)
- User says: "sync release", "release-sync", "check outdated", "verify distributions", "/release-sync"
Authoritative sources
| Truth | Path |
|---|
| Project version | gradle.properties → argusVersion |
| Pinned framework versions | gradle.properties → nettyVersion, junitVersion |
| Module list | settings.gradle.kts |
| Java baseline | root build.gradle.kts toolchain |
Targets
Channel inventory
| Channel | Files | Version surface |
|---|
| Maven Central (starter) | argus-spring-boot-starter/build.gradle.kts | Spring Boot, Spring Context, Micrometer, configuration-processor versions |
| Helm chart | charts/argus/Chart.yaml, charts/argus/values.yaml, charts/argus/templates/*.yaml, charts/argus/README.md | version, appVersion, kubeVersion, image tag, K8s API versions |
| Docker compose | deploy/docker-compose.yml | image tags (must NOT be :latest) |
| Dockerfiles | Dockerfile, deploy/docker/Dockerfile.* (production only; *.example files use :latest deliberately as templates) | base image tag (e.g., eclipse-temurin:21-jre-alpine) |
| Install (Unix) | install.sh | VERSION fallback, ASPROF_VERSION, checksum verification logic |
| Install (Windows) | install.ps1 | Version fallback, example block |
| Homebrew | Formula/argus.rb | version, url, sha256, depends_on JDK version |
| SDKMAN | deploy/sdkman/argus-candidate.json, deploy/sdkman/README.md | candidate version |
| GitHub Action | action/action.yml | version input default |
| CI workflows | .github/workflows/{ci,release,docker,native-image,pages}.yml | actions/checkout@v?, actions/setup-java@v?, JDK version, runner |
Upstream "known-good" baselines (update this table when bumping)
These are the current stable minima. Refresh only when the user asks for a sweep.
| Library / image | Minimum acceptable | Why |
|---|
| Netty | 4.1.115.Final | CVE-2024-47535 patched here |
| JUnit Jupiter | 5.11.x | Bug fixes vs 5.10 |
| Spring Boot (compileOnly) | 3.2.0 (LTS-equivalent OK) | Argus targets Spring Boot 3.2+ |
| Micrometer | 1.12.0 (1.13.x+ preferred for VT metrics) | Virtual Thread metric surface |
actions/checkout | v4 | v3 deprecated track |
actions/setup-java | v4 | v3 deprecated track |
eclipse-temurin base | 21-jre-alpine | Project Java baseline |
prom/prometheus | a pinned vX.Y.Z, never latest | reproducibility |
grafana/grafana | a pinned X.Y.Z, never latest | reproducibility |
| Kubernetes API | apps/v1, networking.k8s.io/v1, monitoring.coreos.com/v1 | K8s 1.25+ removed *beta1 variants |
| async-profiler | install-time and runtime versions MUST match — see §2.4 cross-source check | install.sh and AsProfDownloader write to the same ~/.argus/lib/async-profiler/ directory; a mismatch silently makes one of the two payloads dead weight |
Procedure
1. Resolve truth
ARGUS_VERSION="$(awk -F= '/^argusVersion=/{print $2}' gradle.properties)"
NETTY="$(awk -F= '/^nettyVersion=/{print $2}' gradle.properties)"
JUNIT="$(awk -F= '/^junitVersion=/{print $2}' gradle.properties)"
echo "TRUTH version=$ARGUS_VERSION netty=$NETTY junit=$JUNIT"
2. Per-channel drift checks
2.1 Helm chart
grep -E '^(version|appVersion|kubeVersion):' charts/argus/Chart.yaml
2.2 Docker compose
grep -nE 'image:\s*[^[:space:]]+:latest' deploy/docker-compose.yml
Any hit is a P0 — pin to a concrete version.
2.3 Dockerfiles
grep -rEn '^FROM ' Dockerfile deploy/docker/
Confirm base image is eclipse-temurin:21-jre-alpine (or the agreed baseline). Flag any divergence.
2.4 install.sh / install.ps1
grep -nE "VERSION=\"v|fallback|Version = \"v" install.sh install.ps1
- Fallback string MUST be
v$ARGUS_VERSION.
install.sh example URLs in the comment header use a recent version.
async-profiler cross-source check (this is the trap that the v1.4.0 verify pass caught — install.sh's ASPROF_VERSION="3.0" shipped for releases while runtime was already pinned to 4.4, making the 267 KB install-time download dead weight):
INSTALL_ASPROF=$(awk -F'"' '/^ASPROF_VERSION=/{print $2}' install.sh)
RUNTIME_ASPROF_DL=$(grep -E '^\s*private static final String ASPROF_VERSION' \
argus-cli/src/main/java/io/argus/cli/provider/jdk/AsProfDownloader.java \
| awk -F'"' '{print $2}')
RUNTIME_ASPROF_CAP=$(grep -E '^\s*public static final String ASPROF_VERSION' \
argus-cli/src/main/java/io/argus/cli/provider/jdk/AsProfCapabilities.java \
| awk -F'"' '{print $2}')
echo "install.sh = $INSTALL_ASPROF"
echo "AsProfDownloader.java = $RUNTIME_ASPROF_DL"
echo "AsProfCapabilities.java = $RUNTIME_ASPROF_CAP"
[ "$INSTALL_ASPROF" = "$RUNTIME_ASPROF_DL" ] && [ "$RUNTIME_ASPROF_DL" = "$RUNTIME_ASPROF_CAP" ] \
&& echo "OK — all three async-profiler version constants agree" \
|| echo "DRIFT — install.sh and runtime async-profiler versions disagree (P1)"
All three values MUST be identical. They share ~/.argus/lib/async-profiler/, so a mismatch means whichever source ran last wins and the other download was wasted bandwidth — or worse, the binary on disk lies about its version. If runtime side bumps, install.sh MUST follow in the same release.
2.5 Homebrew Formula
grep -E "(version|url|sha256)" Formula/argus.rb
2.6 SDKMAN
grep -E '"version"|"url"' deploy/sdkman/argus-candidate.json
Version field equals $ARGUS_VERSION.
2.7 GitHub Action
grep -nE '(version|default):' action/action.yml
version input default should be $ARGUS_VERSION or latest — confirm with user which convention this repo uses.
2.8 CI workflows
grep -rnE 'uses: [a-z-]+/[a-z-]+@v[0-9]+' .github/workflows/
grep -rnE 'java-version: ' .github/workflows/
Compare action @vN against the baseline table. JDK version should match the project toolchain (21).
2.9 Spring Boot starter dependencies
grep -E "compileOnly|annotationProcessor|api\(" argus-spring-boot-starter/build.gradle.kts
Compare against baseline minima above. Spring Boot can stay at 3.2.0 if intentional, but flag < 3.2.0 as a hard fail.
2.10 Outdated framework versions in gradle.properties
cat gradle.properties
Compare to baseline minima. Netty < 4.1.115.Final is a P0 (CVE).
2.11 Post-release artifact verification
A green release.yml run is not proof every distribution channel succeeded. Each tag-triggered workflow has independent jobs, and one can fail silently while docs continue to reference the URL/tag that was supposed to be produced. Always cross-check the artifacts, not just the run status.
For the most recent published tag (or the tag passed by the user), verify each channel:
LATEST_TAG="$(gh release view --json tagName -q .tagName)"
for WF in release.yml docker.yml native-image.yml; do
echo "=== $WF ==="
gh run list --workflow "$WF" --branch "$LATEST_TAG" --limit 3 \
--json conclusion,headBranch,event,name,databaseId,createdAt
done
RUN_ID=$(gh run list --workflow docker.yml --branch "$LATEST_TAG" --limit 1 --json databaseId -q '.[0].databaseId')
gh run view "$RUN_ID" --json jobs -q '.jobs[] | "\(.name): \(.conclusion)"'
VERSION="${LATEST_TAG#v}"
OWNER_LC=$(echo "$GITHUB_REPOSITORY_OWNER" | tr 'A-Z' 'a-z')
for IMAGE in argus argus-agent; do
TOKEN=$(curl -s "https://ghcr.io/token?scope=repository:${OWNER_LC}/${IMAGE}:pull" | jq -r .token)
HTTP=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json" \
)
gh release view --json assets -q
Expected for a healthy 1.x release:
release.yml: success, with argus-agent.jar, argus-server.jar, argus-cli-X.Y.Z-all.jar listed under release assets.
docker.yml: every job (Build CLI image, Build agent image) success. Manifest fetch returns HTTP 200 for both argus and argus-agent.
native-image.yml: success if the project ships native binaries; if the upload step fails, install.sh falls back to JAR (which is fine but flag it so the user knows their native artifact is missing).
Red flags this check is meant to catch:
- A run is marked
failure but only one of N jobs failed, and the published-version assumption silently breaks (e.g., agent image missing while CLI was fine).
- Workflow succeeded but
gh release view shows no assets attached (action-gh-release misconfig).
- A
latest tag in GHCR points to a stale digest because the new push was rejected.
If a channel is missing for the current argusVersion:
- Identify the failing job from
gh run view --log-failed.
- Fix the workflow on a branch (do not retag
vX.Y.Z in place — Git tags are immutable on consumers' machines).
- After the fix is merged to
master, re-run via workflow_dispatch against the existing tag, or cut a vX.Y.(Z+1) patch release.
3. Fix policy
- Pure version swaps with a clear baseline (Helm appVersion, install fallback, compose pin): edit directly.
- Dependency bumps that touch
gradle.properties or starter build.gradle.kts: run ./gradlew compileJava and ./gradlew :argus-cli:test after the edit; revert if it breaks.
- Homebrew
sha256: never guess. Either fetch the release artifact and compute, or escalate.
- Deprecated K8s APIs: replace per K8s migration guide; do not silently delete a resource.
- GitHub Action default version: ask the user — some projects pin to specific tags, some prefer
latest.
4. Verify
./gradlew compileJava --quiet
./gradlew :argus-cli:test --quiet
helm lint charts/argus
docker compose -f deploy/docker-compose.yml config >/dev/null
Output format
release-sync report
===================
Truth: version=1.2.0 netty=4.1.115.Final junit=5.11.4
Channel matrix:
starter : OK (Spring Boot 3.2.0 compileOnly, Micrometer 1.12.0)
helm : FIXED Chart.yaml +kubeVersion: ">=1.23.0-0"
docker : FIXED prom/prometheus:latest → :v2.55.0; grafana/grafana:latest → 11.3.0
install.sh : FIXED fallback v1.1.0 → v1.2.0
install.ps1 : FIXED fallback v0.4.0 → v1.2.0; example block
formula : OK
sdkman : OK
action.yml : OK (default version: latest, by design)
ci-workflows : OK (actions @v4, JDK 21)
Dep bumps:
netty 4.1.104.Final → 4.1.115.Final (CVE-2024-47535)
junit 5.10.1 → 5.11.4
Verification:
./gradlew compileJava → exit 0
./gradlew :argus-cli:test → exit 0
Released-tag verification (v1.2.0):
release.yml : success
docker.yml / Build CLI image : success
docker.yml / Build agent image : FAILURE ← P0
native-image.yml : success
ghcr.io/<owner>/argus:1.2.0 : 200 OK
ghcr.io/<owner>/argus-agent:1.2.0 : 404 missing ← P0
release assets : argus-cli-1.2.0-all.jar, argus-agent.jar, argus-server.jar
Escalated to user:
- docker.yml build-agent job failed for v1.2.0 — agent image is not on GHCR even though docs reference it. Fix workflow, then re-run via workflow_dispatch on the v1.2.0 tag or cut v1.2.1.
- Homebrew Formula sha256 — release artifact not yet uploaded; rerun after release publish.
Project rules to honor
- Never commit to master directly — finish on a branch and propose a PR.
- Don't push tags; the release workflow handles that on a tag push.
- Don't bump
argusVersion from this skill — that belongs to the release flow.
- Never write
--no-verify or skip hooks.
- Don't invent SHA256 or release URLs; compute them or escalate.
Out of scope
- Editing user-facing prose / READMEs / site copy → use
docs-sync.
- Publishing to Maven Central (signing, Sonatype upload) — release workflow only.
- Generating SBOM / SLSA attestation — separate concern; flag if missing but don't implement here.