Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
44 changes: 44 additions & 0 deletions .config/rollup.dist.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
const {
CONSTANTS,
INLINED_SOCKET_CLI_LEGACY_BUILD,
INLINED_SOCKET_CLI_PUBLISHED_BUILD,
INLINED_SOCKET_CLI_SENTRY_BUILD,
INSTRUMENT_WITH_SENTRY,
NODE_MODULES,
Expand Down Expand Up @@ -79,6 +80,48 @@ async function copyInitGradle() {
await fs.copyFile(filepath, destPath)
}

// Copy the JVM build-tool resolution assets (Gradle init script, sbt plugin,
// Maven extension jar) into dist/manifest-scripts, where run.mts resolves them
// at runtime. The Maven jar is compiled by maven-extension/build-jar.sh (run in
// CI / local dev) and is absent from a fresh checkout — copy it only if present;
// run.mts surfaces a build hint when it's missing.
async function copyManifestScripts() {
const srcDir = path.join(constants.srcPath, 'commands/manifest/scripts')
const destDir = path.join(constants.distPath, 'manifest-scripts')
await fs.mkdir(path.join(destDir, 'maven-extension'), { recursive: true })
await Promise.all([
fs.copyFile(
path.join(srcDir, 'socket-facts.init.gradle'),
path.join(destDir, 'socket-facts.init.gradle'),
),
fs.copyFile(
path.join(srcDir, 'socket-facts.plugin.scala'),
path.join(destDir, 'socket-facts.plugin.scala'),
),
])
const jarPath = path.join(
srcDir,
'maven-extension',
'coana-maven-extension.jar',
)
if (existsSync(jarPath)) {
await fs.copyFile(
jarPath,
path.join(destDir, 'maven-extension', 'coana-maven-extension.jar'),
)
} else if (constants.ENV[INLINED_SOCKET_CLI_PUBLISHED_BUILD]) {
// Fail closed: a published build without the jar would ship a package whose
// `socket manifest maven` / Maven reachability silently produces an empty
// SBOM. Run `pnpm run build:maven-extension` before `build:dist`. (A local
// dev build tolerates a missing jar; run.mts surfaces a hint at runtime.)
throw new Error(
'Maven manifest extension jar not found at ' +
jarPath +
' for a published build. Build it first: pnpm run build:maven-extension',
)
}
}

async function copyBashCompletion() {
const filepath = path.join(
constants.srcPath,
Expand Down Expand Up @@ -464,6 +507,7 @@ export default async () => {
async writeBundle() {
await Promise.all([
copyInitGradle(),
copyManifestScripts(),
copyBashCompletion(),
updatePackageJson(),
// Remove dist/vendor.js.map file.
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/maven-extension-jar.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Maven extension jar

# Builds (and smoke-tests) the Maven manifest extension jar in CI, separately
# from release. Uses only allowlisted actions — notably NOT actions/setup-java
# (the org allowlist forbids it), so it relies on a JDK pre-installed on the
# runner via JAVA_HOME_17_X64, the same approach provenance.yml uses to build
# the jar at release. Runs on changes to the extension and on demand.

on:
pull_request:
paths:
- 'src/commands/manifest/scripts/maven-extension/**'
- 'src/commands/manifest/scripts/test/maven-compat/**'
- '.github/workflows/maven-extension-jar.yml'
workflow_dispatch:

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Build the Maven extension jar (pre-installed JDK; no setup-java)
run: |
if [ -n "${JAVA_HOME_17_X64:-}" ]; then
export JAVA_HOME="$JAVA_HOME_17_X64"
fi
java -version
bash src/commands/manifest/scripts/maven-extension/build-jar.sh
- name: Verify the jar was produced
run: test -f src/commands/manifest/scripts/maven-extension/coana-maven-extension.jar
- name: Smoke-test the extension on Maven 3.9.9
run: |
if [ -n "${JAVA_HOME_17_X64:-}" ]; then
export JAVA_HOME="$JAVA_HOME_17_X64"
fi
ver=3.9.9
curl -fsSL "https://archive.apache.org/dist/maven/maven-3/$ver/binaries/apache-maven-$ver-bin.zip" -o maven.zip
unzip -q maven.zip
bash src/commands/manifest/scripts/test/maven-compat/smoke-test.sh \
"$PWD/apache-maven-$ver/bin/mvn" \
"$PWD/src/commands/manifest/scripts/maven-extension/coana-maven-extension.jar"
12 changes: 12 additions & 0 deletions .github/workflows/provenance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,18 @@ jobs:
- name: Install dependencies
run: pnpm install --loglevel error

# Compile the Maven manifest extension jar so the dist build bundles it
# into dist/manifest-scripts (the jar is never committed; it ships only in
# the published package). The org action allowlist forbids actions/setup-java,
# so use a JDK pre-installed on the runner image (JAVA_HOME_17_X64), falling
# back to the runner's default `java`. build-jar.sh uses the Maven wrapper.
- name: Build Maven manifest extension jar
run: |
if [ -n "${JAVA_HOME_17_X64:-}" ]; then
export JAVA_HOME="$JAVA_HOME_17_X64"
fi
pnpm run build:maven-extension

- run: INLINED_SOCKET_CLI_PUBLISHED_BUILD=1 pnpm run build:dist
- name: Publish socket
id: publish_socket
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.

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

## [1.1.132](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.132) - 2026-06-30

### Changed
- 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.
- `socket manifest` and `--auto-manifest` now prefer your project's build-tool wrapper (`./gradlew`, `./mvnw`) when present, falling back to `gradle`/`mvn` on PATH.
- Updated the Coana CLI to v `15.6.3`.

## [1.1.131](https://github.com/SocketDev/socket-cli/releases/tag/v1.1.131) - 2026-06-29

### Changed
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "socket",
"version": "1.1.131",
"version": "1.1.132",
"description": "CLI for Socket.dev",
"homepage": "https://github.com/SocketDev/socket-cli",
"license": "MIT",
Expand Down Expand Up @@ -36,6 +36,7 @@
"build:dist": "pnpm build:dist:src && pnpm build:dist:types",
"build:dist:src": "run-p -c clean:dist clean:external && dotenvx -q run -f .env.local -- rollup -c .config/rollup.dist.config.mjs",
"build:dist:types": "pnpm clean:dist:types && tsgo --project tsconfig.dts.json",
"build:maven-extension": "bash src/commands/manifest/scripts/maven-extension/build-jar.sh",
"build:sea": "node src/sea/build-sea.mts",
"build:sea:internal:bootstrap": "rollup -c .config/rollup.sea.config.mjs",
"check": "pnpm check:lint && pnpm check:tsc",
Expand Down Expand Up @@ -96,7 +97,7 @@
"@babel/preset-typescript": "7.27.1",
"@babel/runtime": "7.28.4",
"@biomejs/biome": "2.2.4",
"@coana-tech/cli": "15.6.2",
"@coana-tech/cli": "15.6.3",
"@cyclonedx/cdxgen": "12.1.2",
"@dotenvx/dotenvx": "1.49.0",
"@eslint/compat": "1.3.2",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions socket.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ version: 2

projectIgnorePaths:
- "test/fixtures/"
# Build-tooling and test fixtures for the JVM manifest scripts, not socket-cli's
# own supply chain: the Maven extension's build pom and the compat-test
# projects' pom.xml / build.gradle / build.sbt.
- "src/commands/manifest/scripts/maven-extension/"
- "src/commands/manifest/scripts/test/"
7 changes: 5 additions & 2 deletions src/commands/manifest/cmd-manifest-gradle.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger'
import { convertGradleToFacts } from './convert-gradle-to-facts.mts'
import { convertGradleToMaven } from './convert_gradle_to_maven.mts'
import { parseBuildToolOpts } from './parse-build-tool-opts.mts'
import { resolveBuildToolBin } from './scripts/build-tool.mts'
import constants, { REQUIREMENTS_TXT, SOCKET_JSON } from '../../constants.mts'
import { commonFlags } from '../../flags.mts'
import { checkCommandInput } from '../../utils/check-input.mts'
Expand All @@ -28,7 +29,8 @@ const config: CliCommandConfig = {
...commonFlags,
bin: {
type: 'string',
description: 'Location of gradlew binary to use, default: CWD/gradlew',
description:
'Location of the gradle binary to use, default: ./gradlew if present, else gradle on PATH',
},
facts: {
type: 'boolean',
Expand Down Expand Up @@ -156,7 +158,8 @@ async function run(
bin = sockJson.defaults?.manifest?.gradle?.bin
logger.info(`Using default --bin from ${SOCKET_JSON}:`, bin)
} else {
bin = path.join(cwd, 'gradlew')
// Prefer the project's ./gradlew wrapper, else `gradle` on PATH.
bin = resolveBuildToolBin('gradle', cwd)
}
}
if (!gradleOpts) {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/manifest/cmd-manifest-gradle.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('socket manifest gradle', async () => {
$ socket manifest gradle [options] [CWD=.]

Options
--bin Location of gradlew binary to use, default: CWD/gradlew
--bin Location of the gradle binary to use, default: ./gradlew if present, else gradle on PATH
--exclude-configs When generating facts: comma-separated glob patterns; Gradle configurations matching any pattern are skipped (applied after --include-configs)
--facts Emit a Socket facts JSON file (\`.socket.facts.json\`) describing the resolved dependency graph. This is the default; pass \`--pom\` to generate \`pom.xml\` files instead
--gradle-opts Additional options to pass on to ./gradlew, see \`./gradlew --help\`
Expand Down
7 changes: 5 additions & 2 deletions src/commands/manifest/cmd-manifest-kotlin.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { logger } from '@socketsecurity/registry/lib/logger'
import { convertGradleToFacts } from './convert-gradle-to-facts.mts'
import { convertGradleToMaven } from './convert_gradle_to_maven.mts'
import { parseBuildToolOpts } from './parse-build-tool-opts.mts'
import { resolveBuildToolBin } from './scripts/build-tool.mts'
import constants, { REQUIREMENTS_TXT, SOCKET_JSON } from '../../constants.mts'
import { commonFlags } from '../../flags.mts'
import { checkCommandInput } from '../../utils/check-input.mts'
Expand Down Expand Up @@ -33,7 +34,8 @@ const config: CliCommandConfig = {
...commonFlags,
bin: {
type: 'string',
description: 'Location of gradlew binary to use, default: CWD/gradlew',
description:
'Location of the gradle binary to use, default: ./gradlew if present, else gradle on PATH',
},
facts: {
type: 'boolean',
Expand Down Expand Up @@ -161,7 +163,8 @@ async function run(
bin = sockJson.defaults?.manifest?.gradle?.bin
logger.info(`Using default --bin from ${SOCKET_JSON}:`, bin)
} else {
bin = path.join(cwd, 'gradlew')
// Prefer the project's ./gradlew wrapper, else `gradle` on PATH.
bin = resolveBuildToolBin('gradle', cwd)
}
}
if (!gradleOpts) {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/manifest/cmd-manifest-kotlin.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('socket manifest kotlin', async () => {
$ socket manifest kotlin [options] [CWD=.]

Options
--bin Location of gradlew binary to use, default: CWD/gradlew
--bin Location of the gradle binary to use, default: ./gradlew if present, else gradle on PATH
--exclude-configs When generating facts: comma-separated glob patterns; Gradle configurations matching any pattern are skipped (applied after --include-configs)
--facts Emit a Socket facts JSON file (\`.socket.facts.json\`) describing the resolved dependency graph. This is the default; pass \`--pom\` to generate \`pom.xml\` files instead
--gradle-opts Additional options to pass on to ./gradlew, see \`./gradlew --help\`
Expand Down
7 changes: 5 additions & 2 deletions src/commands/manifest/cmd-manifest-maven.mts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { logger } from '@socketsecurity/registry/lib/logger'

import { convertMavenToFacts } from './convert-maven-to-facts.mts'
import { parseBuildToolOpts } from './parse-build-tool-opts.mts'
import { resolveBuildToolBin } from './scripts/build-tool.mts'
import constants, { SOCKET_JSON } from '../../constants.mts'
import { commonFlags } from '../../flags.mts'
import { checkCommandInput } from '../../utils/check-input.mts'
Expand All @@ -27,7 +28,8 @@ const config: CliCommandConfig = {
...commonFlags,
bin: {
type: 'string',
description: 'Location of the maven binary to use, default: mvn on PATH',
description:
'Location of the maven binary to use, default: ./mvnw if present, else mvn on PATH',
},
includeConfigs: {
type: 'string',
Expand Down Expand Up @@ -136,7 +138,8 @@ async function run(
bin = sockJson.defaults?.manifest?.maven?.bin
logger.info(`Using default --bin from ${SOCKET_JSON}:`, bin)
} else {
bin = 'mvn'
// Prefer the project's ./mvnw wrapper, else `mvn` on PATH.
bin = resolveBuildToolBin('maven', cwd)
}
}
if (!mavenOpts) {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/manifest/cmd-manifest-maven.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('socket manifest maven', async () => {
$ socket manifest maven [options] [CWD=.]

Options
--bin Location of the maven binary to use, default: mvn on PATH
--bin Location of the maven binary to use, default: ./mvnw if present, else mvn on PATH
--exclude-configs Comma-separated glob patterns; Maven scopes matching any pattern are skipped (applied after --include-configs)
--ignore-unresolved Warn on unresolved dependencies instead of failing the run (unresolved deps are not emitted to the facts file)
--include-configs Comma-separated glob patterns matched against Maven dependency scopes (case-sensitive, \`*\` and \`?\` wildcards). Only scopes matching at least one pattern are resolved. e.g. \`compile,runtime\`. Default: every scope
Expand Down
Loading
Loading