Skip to content

Commit aab5687

Browse files
committed
feat(manifest): generate JVM Socket facts natively + single-run reachability sidecar (1.1.132, Coana 15.6.3)
Move the JVM build-tool resolution scripts (Gradle init script, sbt plugin, Maven core extension) and the TypeScript SBOM assembler into socket-cli, so `socket manifest` and `--auto-manifest` generate `.socket.facts.json` natively instead of delegating to the Coana CLI's `manifest` command. On `socket scan create --reach --auto-manifest` the build tool now runs exactly once and emits both the SBOM and a resolved-paths sidecar, passed to `coana run --compute-artifacts-sidecar`. Coana no longer re-resolves the build at reach time, eliminating the divergence that broke dynamically-versioned projects (git-derived versions, CI build numbers, timestamps). Build-tool binary selection prefers the project's wrapper (./gradlew, ./mvnw) and falls back to gradle/mvn on PATH. Bumps @coana-tech/cli to 15.6.3, which ships `--compute-artifacts-sidecar`.
1 parent 94484ea commit aab5687

69 files changed

Lines changed: 5042 additions & 417 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.config/rollup.dist.config.mjs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,38 @@ async function copyInitGradle() {
7979
await fs.copyFile(filepath, destPath)
8080
}
8181

82+
// Copy the JVM build-tool resolution assets (Gradle init script, sbt plugin,
83+
// Maven extension jar) into dist/manifest-scripts, where run.mts resolves them
84+
// at runtime. The Maven jar is compiled by maven-extension/build-jar.sh (run in
85+
// CI / local dev) and is absent from a fresh checkout — copy it only if present;
86+
// run.mts surfaces a build hint when it's missing.
87+
async function copyManifestScripts() {
88+
const srcDir = path.join(constants.srcPath, 'commands/manifest/scripts')
89+
const destDir = path.join(constants.distPath, 'manifest-scripts')
90+
await fs.mkdir(path.join(destDir, 'maven-extension'), { recursive: true })
91+
await Promise.all([
92+
fs.copyFile(
93+
path.join(srcDir, 'socket-facts.init.gradle'),
94+
path.join(destDir, 'socket-facts.init.gradle'),
95+
),
96+
fs.copyFile(
97+
path.join(srcDir, 'socket-facts.plugin.scala'),
98+
path.join(destDir, 'socket-facts.plugin.scala'),
99+
),
100+
])
101+
const jarPath = path.join(
102+
srcDir,
103+
'maven-extension',
104+
'coana-maven-extension.jar',
105+
)
106+
if (existsSync(jarPath)) {
107+
await fs.copyFile(
108+
jarPath,
109+
path.join(destDir, 'maven-extension', 'coana-maven-extension.jar'),
110+
)
111+
}
112+
}
113+
82114
async function copyBashCompletion() {
83115
const filepath = path.join(
84116
constants.srcPath,
@@ -464,6 +496,7 @@ export default async () => {
464496
async writeBundle() {
465497
await Promise.all([
466498
copyInitGradle(),
499+
copyManifestScripts(),
467500
copyBashCompletion(),
468501
updatePackageJson(),
469502
// Remove dist/vendor.js.map file.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
name: Manifest compat
2+
3+
# Reusable: build-tool version compatibility for ONE ecosystem's manifest script.
4+
# Called by manifest-gradle.yml / manifest-sbt.yml / manifest-maven.yml when their
5+
# label is added to a PR, so each ecosystem is its own workflow (and its own PR
6+
# check group). Runs the real script across a version matrix to assert it emits
7+
# the expected RECORDS (the TS assembler is covered by unit tests).
8+
9+
on:
10+
workflow_call:
11+
inputs:
12+
tool:
13+
description: gradle | maven | sbt
14+
required: true
15+
type: string
16+
17+
permissions:
18+
contents: read
19+
20+
jobs:
21+
# The label is a momentary "run" button: remove it as soon as the run starts so
22+
# re-adding it re-triggers a fresh run (and the PR doesn't stay labeled).
23+
unlabel:
24+
runs-on: ubuntu-latest
25+
permissions:
26+
pull-requests: write
27+
steps:
28+
- env:
29+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30+
REPO: ${{ github.repository }}
31+
PR: ${{ github.event.pull_request.number }}
32+
LABEL: ${{ github.event.label.name }}
33+
run: gh api --method DELETE "repos/$REPO/issues/$PR/labels/$LABEL" || true
34+
35+
setup:
36+
runs-on: ubuntu-latest
37+
outputs:
38+
matrix: ${{ steps.m.outputs.matrix }}
39+
steps:
40+
- id: m
41+
env:
42+
TOOL: ${{ inputs.tool }}
43+
run: |
44+
if [ "$TOOL" = gradle ]; then
45+
# 1.12: all three reflective fallbacks; 2.14.1: findProperty/firstLevel; 3.3: native
46+
# canBeResolved; 8.10.2: modern; 9.2.1: latest.
47+
matrix='{"include":[{"tool":"gradle","ver":"1.12","java":"8"},{"tool":"gradle","ver":"2.14.1","java":"8"},{"tool":"gradle","ver":"3.3","java":"8"},{"tool":"gradle","ver":"8.10.2","java":"17"},{"tool":"gradle","ver":"9.2.1","java":"21"}]}'
48+
elif [ "$TOOL" = maven ]; then
49+
# Runtime compat of the core extension across the Maven 3.6/3.8/3.9 line.
50+
matrix='{"include":[{"tool":"maven","ver":"3.6.3","java":"11"},{"tool":"maven","ver":"3.8.8","java":"17"},{"tool":"maven","ver":"3.9.9","java":"17"}]}'
51+
else
52+
# 0.13.18: Scala 2.10 / reflective 0.13 shims; then 1.x.
53+
matrix='{"include":[{"tool":"sbt","ver":"0.13.18","scala":"2.10.7","java":"8"},{"tool":"sbt","ver":"1.4.9","scala":"2.12.20","java":"11"},{"tool":"sbt","ver":"1.6.2","scala":"2.12.20","java":"17"},{"tool":"sbt","ver":"1.9.9","scala":"2.12.20","java":"17"}]}'
54+
fi
55+
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
56+
57+
compat:
58+
needs: setup
59+
name: ${{ matrix.tool }} ${{ matrix.ver }}
60+
runs-on: ubuntu-latest
61+
strategy:
62+
fail-fast: false
63+
matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
64+
steps:
65+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
66+
with:
67+
persist-credentials: false
68+
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
69+
with:
70+
distribution: 'temurin'
71+
java-version: ${{ matrix.java }}
72+
- uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
73+
with:
74+
python-version: '3.12'
75+
# matrix.* via env (not inlined): the matrix is generated dynamically, so its
76+
# values are treated as untrusted in run shells.
77+
- name: Download Gradle ${{ matrix.ver }}
78+
if: matrix.tool == 'gradle'
79+
env:
80+
VER: ${{ matrix.ver }}
81+
run: |
82+
curl -fsSL "https://services.gradle.org/distributions/gradle-$VER-bin.zip" -o gradle.zip
83+
unzip -q gradle.zip
84+
- name: Gradle smoke test (offline, local repo)
85+
if: matrix.tool == 'gradle'
86+
env:
87+
VER: ${{ matrix.ver }}
88+
run: bash src/commands/manifest/scripts/test/gradle-compat/smoke-test.sh "$PWD/gradle-$VER/bin/gradle"
89+
- uses: sbt/setup-sbt@3e125ece5c3e5248e18da9ed8d2cce3d335ec8dd # v1.1.14
90+
if: matrix.tool == 'sbt'
91+
with:
92+
sbt-runner-version: 1.9.9
93+
- name: SBT smoke test (sbt ${{ matrix.ver }})
94+
if: matrix.tool == 'sbt'
95+
env:
96+
VER: ${{ matrix.ver }}
97+
SCALA: ${{ matrix.scala }}
98+
run: bash src/commands/manifest/scripts/test/sbt-compat/smoke-test.sh "$VER" "$SCALA"
99+
# Build the extension jar from source with the runner's default Maven, then run the smoke project
100+
# on the matrix Maven version (runtime compat is what varies, not the build).
101+
- name: Build Maven extension jar
102+
if: matrix.tool == 'maven'
103+
run: bash src/commands/manifest/scripts/maven-extension/build-jar.sh
104+
- name: Download Maven ${{ matrix.ver }}
105+
if: matrix.tool == 'maven'
106+
env:
107+
VER: ${{ matrix.ver }}
108+
run: |
109+
curl -fsSL "https://archive.apache.org/dist/maven/maven-3/$VER/binaries/apache-maven-$VER-bin.zip" -o maven.zip
110+
unzip -q maven.zip
111+
- name: Maven smoke test (maven ${{ matrix.ver }})
112+
if: matrix.tool == 'maven'
113+
env:
114+
VER: ${{ matrix.ver }}
115+
run: |
116+
bash src/commands/manifest/scripts/test/maven-compat/smoke-test.sh \
117+
"$PWD/apache-maven-$VER/bin/mvn" \
118+
"$PWD/src/commands/manifest/scripts/maven-extension/coana-maven-extension.jar"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Manifest gradle compat
2+
3+
# On-demand: add the `manifest-gradle` label to a PR to run the Gradle init
4+
# script's compat matrix across Gradle versions (re-add to re-run). Its own
5+
# workflow so it shows as its own PR check group.
6+
7+
on:
8+
pull_request:
9+
types: [labeled]
10+
11+
permissions:
12+
contents: read
13+
14+
concurrency:
15+
group: ${{ github.ref }}-manifest-gradle
16+
cancel-in-progress: true
17+
18+
jobs:
19+
gradle:
20+
if: github.event.label.name == 'manifest-gradle'
21+
permissions:
22+
contents: read
23+
pull-requests: write
24+
uses: ./.github/workflows/manifest-compat.yml
25+
with:
26+
tool: gradle
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Manifest maven compat
2+
3+
# On-demand: add the `manifest-maven` label to a PR to compile the Maven core
4+
# extension and run its compat matrix across Maven versions (re-add to re-run).
5+
# Its own workflow so it shows as its own PR check group.
6+
7+
on:
8+
pull_request:
9+
types: [labeled]
10+
11+
permissions:
12+
contents: read
13+
14+
concurrency:
15+
group: ${{ github.ref }}-manifest-maven
16+
cancel-in-progress: true
17+
18+
jobs:
19+
maven:
20+
if: github.event.label.name == 'manifest-maven'
21+
permissions:
22+
contents: read
23+
pull-requests: write
24+
uses: ./.github/workflows/manifest-compat.yml
25+
with:
26+
tool: maven

.github/workflows/manifest-sbt.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Manifest sbt compat
2+
3+
# On-demand: add the `manifest-sbt` label to a PR to run the sbt plugin's compat
4+
# matrix across sbt versions (re-add to re-run). Its own workflow so it shows as
5+
# its own PR check group.
6+
7+
on:
8+
pull_request:
9+
types: [labeled]
10+
11+
permissions:
12+
contents: read
13+
14+
concurrency:
15+
group: ${{ github.ref }}-manifest-sbt
16+
cancel-in-progress: true
17+
18+
jobs:
19+
sbt:
20+
if: github.event.label.name == 'manifest-sbt'
21+
permissions:
22+
contents: read
23+
pull-requests: write
24+
uses: ./.github/workflows/manifest-compat.yml
25+
with:
26+
tool: sbt

.github/workflows/provenance.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,16 @@ jobs:
204204
- name: Install dependencies
205205
run: pnpm install --loglevel error
206206

207+
# Compile the Maven manifest extension jar so the dist build bundles it
208+
# into dist/manifest-scripts (the jar is never committed; it ships only in
209+
# the published package). Needs a JDK; build-jar.sh uses the Maven wrapper.
210+
- uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
211+
with:
212+
distribution: 'temurin'
213+
java-version: '17'
214+
- name: Build Maven manifest extension jar
215+
run: pnpm run build:maven-extension
216+
207217
- run: INLINED_SOCKET_CLI_PUBLISHED_BUILD=1 pnpm run build:dist
208218
- name: Publish socket
209219
id: publish_socket

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [1.1.132](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.132) - 2026-06-30
8+
9+
### Changed
10+
- More reliable reachability for Gradle, sbt, and Maven projects with dynamic versions (git versions, CI build numbers, timestamps): the build is resolved once and its artifact paths reused, avoiding spurious "failed to install" errors.
11+
- `socket manifest` and `--auto-manifest` now prefer your project's build-tool wrapper (`./gradlew`, `./mvnw`) when present, falling back to `gradle`/`mvn` on PATH.
12+
- Updated the Coana CLI to v `15.6.3`.
13+
714
## [1.1.131](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.131) - 2026-06-29
815

916
### Changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "socket",
3-
"version": "1.1.131",
3+
"version": "1.1.132",
44
"description": "CLI for Socket.dev",
55
"homepage": "https://github.com/SocketDev/socket-cli",
66
"license": "MIT",
@@ -36,6 +36,7 @@
3636
"build:dist": "pnpm build:dist:src && pnpm build:dist:types",
3737
"build:dist:src": "run-p -c clean:dist clean:external && dotenvx -q run -f .env.local -- rollup -c .config/rollup.dist.config.mjs",
3838
"build:dist:types": "pnpm clean:dist:types && tsgo --project tsconfig.dts.json",
39+
"build:maven-extension": "bash src/commands/manifest/scripts/maven-extension/build-jar.sh",
3940
"build:sea": "node src/sea/build-sea.mts",
4041
"build:sea:internal:bootstrap": "rollup -c .config/rollup.sea.config.mjs",
4142
"check": "pnpm check:lint && pnpm check:tsc",
@@ -96,7 +97,7 @@
9697
"@babel/preset-typescript": "7.27.1",
9798
"@babel/runtime": "7.28.4",
9899
"@biomejs/biome": "2.2.4",
99-
"@coana-tech/cli": "15.6.2",
100+
"@coana-tech/cli": "15.6.3",
100101
"@cyclonedx/cdxgen": "12.1.2",
101102
"@dotenvx/dotenvx": "1.49.0",
102103
"@eslint/compat": "1.3.2",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

socket.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,8 @@ version: 2
22

33
projectIgnorePaths:
44
- "test/fixtures/"
5+
# Build-tooling and test fixtures for the JVM manifest scripts, not socket-cli's
6+
# own supply chain: the Maven extension's build pom and the compat-test
7+
# projects' pom.xml / build.gradle / build.sbt.
8+
- "src/commands/manifest/scripts/maven-extension/"
9+
- "src/commands/manifest/scripts/test/"

0 commit comments

Comments
 (0)