Skip to content

Commit 01fcc16

Browse files
committed
merge v1.x: adopt landed --bazel-flag, keep startup-flag + maven-repo
2 parents 3346783 + 26f6c22 commit 01fcc16

149 files changed

Lines changed: 12438 additions & 3171 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: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
const {
3535
CONSTANTS,
3636
INLINED_SOCKET_CLI_LEGACY_BUILD,
37+
INLINED_SOCKET_CLI_PUBLISHED_BUILD,
3738
INLINED_SOCKET_CLI_SENTRY_BUILD,
3839
INSTRUMENT_WITH_SENTRY,
3940
NODE_MODULES,
@@ -79,22 +80,46 @@ async function copyInitGradle() {
7980
await fs.copyFile(filepath, destPath)
8081
}
8182

82-
async function copySocketFactsInitGradle() {
83-
const filepath = path.join(
84-
constants.srcPath,
85-
'commands/manifest/socket-facts.init.gradle',
86-
)
87-
const destPath = path.join(constants.distPath, 'socket-facts.init.gradle')
88-
await fs.copyFile(filepath, destPath)
89-
}
90-
91-
async function copySocketFactsSbtPlugin() {
92-
const filepath = path.join(
93-
constants.srcPath,
94-
'commands/manifest/socket-facts.plugin.scala',
83+
// Copy the JVM build-tool resolution assets (Gradle init script, sbt plugin,
84+
// Maven extension jar) into dist/manifest-scripts, where run.mts resolves them
85+
// at runtime. The Maven jar is compiled by maven-extension/build-jar.sh (run in
86+
// CI / local dev) and is absent from a fresh checkout — copy it only if present;
87+
// run.mts surfaces a build hint when it's missing.
88+
async function copyManifestScripts() {
89+
const srcDir = path.join(constants.srcPath, 'commands/manifest/scripts')
90+
const destDir = path.join(constants.distPath, 'manifest-scripts')
91+
await fs.mkdir(path.join(destDir, 'maven-extension'), { recursive: true })
92+
await Promise.all([
93+
fs.copyFile(
94+
path.join(srcDir, 'socket-facts.init.gradle'),
95+
path.join(destDir, 'socket-facts.init.gradle'),
96+
),
97+
fs.copyFile(
98+
path.join(srcDir, 'socket-facts.plugin.scala'),
99+
path.join(destDir, 'socket-facts.plugin.scala'),
100+
),
101+
])
102+
const jarPath = path.join(
103+
srcDir,
104+
'maven-extension',
105+
'coana-maven-extension.jar',
95106
)
96-
const destPath = path.join(constants.distPath, 'socket-facts.plugin.scala')
97-
await fs.copyFile(filepath, destPath)
107+
if (existsSync(jarPath)) {
108+
await fs.copyFile(
109+
jarPath,
110+
path.join(destDir, 'maven-extension', 'coana-maven-extension.jar'),
111+
)
112+
} else if (constants.ENV[INLINED_SOCKET_CLI_PUBLISHED_BUILD]) {
113+
// Fail closed: a published build without the jar would ship a package whose
114+
// `socket manifest maven` / Maven reachability silently produces an empty
115+
// SBOM. Run `pnpm run build:maven-extension` before `build:dist`. (A local
116+
// dev build tolerates a missing jar; run.mts surfaces a hint at runtime.)
117+
throw new Error(
118+
'Maven manifest extension jar not found at ' +
119+
jarPath +
120+
' for a published build. Build it first: pnpm run build:maven-extension',
121+
)
122+
}
98123
}
99124

100125
async function copyBashCompletion() {
@@ -139,7 +164,13 @@ async function copyExternalPackages() {
139164
// Cleanup package files.
140165
await Promise.all(
141166
[
142-
[blessedPath, ['lib/**/*.js', 'usr/**/**', 'vendor/**/*.js']],
167+
// Keep blessed's terminfo (the flat files in usr/, e.g. usr/xterm) but
168+
// NOT usr/fonts/** — the OFL-1.1 Terminus bitmap font is only used by the
169+
// unused BigText widget, and shipping it forces an OFL-1.1 license. The
170+
// 'usr/*' glob matches one level deep, so usr/fonts/<file> is dropped.
171+
// Re-verify usr/ contents on a blessed upgrade (a nested terminfo dir
172+
// would be dropped too).
173+
[blessedPath, ['lib/**/*.js', 'usr/*', 'vendor/**/*.js']],
143174
[blessedContribPath, ['lib/**/*.js', 'index.js']],
144175
[
145176
socketRegistryPath,
@@ -476,8 +507,7 @@ export default async () => {
476507
async writeBundle() {
477508
await Promise.all([
478509
copyInitGradle(),
479-
copySocketFactsInitGradle(),
480-
copySocketFactsSbtPlugin(),
510+
copyManifestScripts(),
481511
copyBashCompletion(),
482512
updatePackageJson(),
483513
// Remove dist/vendor.js.map file.

.github/workflows/provenance.yml

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,15 @@ jobs:
2626
runs-on: ubuntu-latest
2727

2828
permissions:
29-
contents: read
29+
# `contents: write` needed to create the v<version> tag via gh api
30+
# at the end of this job. Token is scoped to the dedicated tag step
31+
# via GH_TOKEN env; never persisted in `.git/config` (checkout keeps
32+
# persist-credentials: false so build/install steps can't reach it).
33+
contents: write
3034
id-token: write # NPM trusted publishing via OIDC
3135

3236
steps:
33-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
37+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 (2026-05-20)
3438
with:
3539
persist-credentials: false
3640

@@ -200,8 +204,26 @@ jobs:
200204
- name: Install dependencies
201205
run: pnpm install --loglevel error
202206

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). Invoke build-jar.sh directly, NOT via `pnpm run`:
210+
# Socket Firewall wraps the package managers (npm/pnpm/...) it shims, so a
211+
# `pnpm run` would route the Maven wrapper's download through sfw, which
212+
# fails on the non-package fetch. Running bash directly keeps the Maven
213+
# download outside the shimmed process tree. The org action allowlist forbids
214+
# actions/setup-java, so use a JDK pre-installed on the runner image
215+
# (JAVA_HOME_17_X64), falling back to the runner's default `java`.
216+
- name: Build Maven manifest extension jar
217+
run: |
218+
if [ -n "${JAVA_HOME_17_X64:-}" ]; then
219+
export JAVA_HOME="$JAVA_HOME_17_X64"
220+
fi
221+
bash src/commands/manifest/scripts/maven-extension/build-jar.sh
222+
203223
- run: INLINED_SOCKET_CLI_PUBLISHED_BUILD=1 pnpm run build:dist
204-
- run: npm publish --provenance --access public --tag "${NPM_DIST_TAG}"
224+
- name: Publish socket
225+
id: publish_socket
226+
run: npm publish --provenance --access public --tag "${NPM_DIST_TAG}"
205227
continue-on-error: true
206228
env:
207229
NPM_DIST_TAG: ${{ inputs.dist-tag }}
@@ -225,3 +247,63 @@ jobs:
225247
NPM_DIST_TAG: ${{ inputs.dist-tag }}
226248
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # zizmor: ignore[secrets-outside-env]
227249
SOCKET_CLI_DEBUG: ${{ inputs.debug }}
250+
251+
# Create v<version> git tag at the published commit SHA after a
252+
# successful socket-package publish, idempotently. GitHub Release
253+
# Immutability ("Disallow assets and tags from being modified once a
254+
# release is published") freezes tags once bound to a Release, so:
255+
# - existing tag at same SHA → no-op
256+
# - existing tag at different SHA → hard-fail (operator recovery
257+
# required)
258+
# Gated on the first publish step (publish_socket — the `socket` npm
259+
# package) actually succeeding; the cli / cli-with-sentry publishes
260+
# use `continue-on-error: true` and don't gate the tag.
261+
#
262+
# Uses gh api (not `git push`) so the token only lives in this step's
263+
# env, never written to `.git/config` by an earlier `actions/checkout`
264+
# with persist-credentials: true (which would leak it to every later
265+
# step including `pnpm install` postinstall scripts).
266+
- name: Tag release (idempotent)
267+
if: steps.publish_socket.outcome == 'success'
268+
env:
269+
GH_TOKEN: ${{ github.token }}
270+
REPO: ${{ github.repository }}
271+
run: |
272+
PUBLISHED_SHA=$(git rev-parse HEAD)
273+
PUBLISHED_VERSION=$(node -p "require('./package.json').version")
274+
TAG="v$PUBLISHED_VERSION"
275+
276+
# Look up any existing tag ref. gh api exits non-zero on 404 (tag
277+
# absent) and writes the error body to stdout, so branch on the
278+
# exit code — never on whether stdout is empty. EXISTING_JSON is
279+
# only valid JSON when the call succeeded.
280+
if EXISTING_JSON=$(gh api "repos/$REPO/git/ref/tags/$TAG" 2>/dev/null); then
281+
# The ref's object is either a commit (lightweight tag) or a tag
282+
# object (annotated/signed tag, e.g. the hand-created `git tag -s`
283+
# tags). For an annotated tag, object.sha is the tag-object SHA,
284+
# not the commit — dereference it via git/tags to get the commit
285+
# the tag actually points at before comparing.
286+
REF_TYPE=$(echo "$EXISTING_JSON" | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).object.type")
287+
REF_OBJECT_SHA=$(echo "$EXISTING_JSON" | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).object.sha")
288+
if [ "$REF_TYPE" = "tag" ]; then
289+
EXISTING_SHA=$(gh api "repos/$REPO/git/tags/$REF_OBJECT_SHA" --jq '.object.sha')
290+
else
291+
EXISTING_SHA="$REF_OBJECT_SHA"
292+
fi
293+
if [ "$EXISTING_SHA" = "$PUBLISHED_SHA" ]; then
294+
echo "Tag $TAG already exists at $PUBLISHED_SHA — no-op."
295+
exit 0
296+
fi
297+
echo "::error::Tag $TAG exists at $EXISTING_SHA but publish SHA is $PUBLISHED_SHA."
298+
echo "::error::Release immutability is enabled; this requires manual recovery:"
299+
echo "::error:: 1. Delete any GitHub Release tied to $TAG"
300+
echo "::error:: 2. Delete the tag via the API"
301+
echo "::error:: 3. Re-run this workflow"
302+
exit 1
303+
fi
304+
305+
gh api "repos/$REPO/git/refs" \
306+
-X POST \
307+
-f "ref=refs/tags/$TAG" \
308+
-f "sha=$PUBLISHED_SHA"
309+
echo "Created tag $TAG at $PUBLISHED_SHA"

0 commit comments

Comments
 (0)