Skip to content
Open
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
250 changes: 248 additions & 2 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ members = [
"src/resolver",
"src/safety",
"src/semver",
"src/sigstore",
"src/sourcemap",
"src/sql",
"src/sys",
Expand Down Expand Up @@ -386,6 +387,7 @@ bun_paths = { path = "src/paths" }
bun_resolver = { path = "src/resolver" }
bun_safety = { path = "src/safety" }
bun_semver = { path = "src/semver" }
bun_sigstore = { path = "src/sigstore" }
bun_sourcemap = { path = "src/sourcemap" }
bun_sql = { path = "src/sql" }
bun_sys = { path = "src/sys" }
Expand Down
27 changes: 27 additions & 0 deletions docs/pm/cli/publish.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,33 @@ Provide a one-time password directly to the CLI. If the password is valid, `bun
bun publish --otp 123456
```

### `--provenance`

Generate a signed [npm provenance](https://docs.npmjs.com/generating-provenance-statements) statement via Sigstore keyless signing and attach it to the published package. Requires `--access public` and a supported CI environment:

- **GitHub Actions** — the workflow must grant `permissions: id-token: write`.
- **GitLab CI** — the job must define `SIGSTORE_ID_TOKEN` under [`id_tokens`](https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html) with audience `sigstore`.

Provenance is also enabled implicitly when `NPM_CONFIG_PROVENANCE=true` (which `actions/setup-node` sets when configured with `provenance: true`). Use `--no-provenance` to override.

```sh terminal icon="terminal"
bun publish --provenance --access public
```
Comment thread
robobun marked this conversation as resolved.

`--provenance` can also be set in the `publishConfig` field of your `package.json`:

```json package.json icon="file-json"
{
"publishConfig": {
"provenance": true
}
}
```

To attach an externally-generated Sigstore bundle instead of generating one, use `--provenance-file <path>`. The bundle's subject must match the package name and tarball digest. `--provenance` and `--provenance-file` are mutually exclusive.

For private Sigstore deployments, the Fulcio/Rekor endpoints can be overridden via `BUN_SIGSTORE_FULCIO_URL`, `BUN_SIGSTORE_REKOR_URL`, `BUN_SIGSTORE_TLOG_BASE_URL`, and `BUN_SIGSTORE_OIDC_AUDIENCE`.

<Note>
`bun publish` respects the `NPM_CONFIG_TOKEN` environment variable, useful when publishing from GitHub Actions or
other automated workflows.
Expand Down
26 changes: 26 additions & 0 deletions docs/snippets/cli/publish.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,32 @@ bun publish --otp 123456

</ParamField>

<ParamField path="--provenance" type="boolean">

Generate a signed npm provenance statement via Sigstore keyless signing. Requires `--access public` and running inside GitHub Actions (with `id-token: write` permission) or GitLab CI (with `SIGSTORE_ID_TOKEN`). Also enabled by `NPM_CONFIG_PROVENANCE=true`; override with `--no-provenance`.

```sh terminal icon="terminal"
bun publish --provenance --access public
```

`--provenance` can also be set in the `publishConfig` field of your `package.json`.

```json package.json icon="file-json"
{
"publishConfig": {
"provenance": true // [!code ++]
}
}
```

</ParamField>

<ParamField path="--provenance-file" type="string">

Path to an externally-generated Sigstore provenance bundle to attach instead of generating one. The bundle's subject must match the package name and tarball digest. Mutually exclusive with `--provenance`.

</ParamField>

### Registry Configuration

#### Custom Registry
Expand Down
12 changes: 11 additions & 1 deletion scripts/verify-baseline-static/allowlist-x64-windows.txt
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ deflate_decompress_bmi2 [BMI2]
# memchr::arch::x86_64::memchr::*_raw::detect / avx2::packedpair::Finder::new.
# PDB DBI records carry demangled Rust names for the directly-linked crate;
# the older v0-mangled detect entries are kept for toolchain drift.
# (14 symbols)
# (15 symbols)
# ----------------------------------------------------------------------------
memchr::arch::x86_64::avx2::memchr::One::find_raw_avx2 [AVX, AVX2]
memchr::arch::x86_64::avx2::memchr::One::rfind_raw_avx2 [AVX, AVX2]
Expand All @@ -837,6 +837,7 @@ memchr::arch::x86_64::memchr::memchr_raw::find_avx2 [AVX, AVX2]
memchr::arch::x86_64::memchr::memchr2_raw::find_avx2 [AVX, AVX2]
memchr::arch::x86_64::memchr::memchr3_raw::find_avx2 [AVX, AVX2]
memchr::arch::x86_64::memchr::memrchr_raw::find_avx2 [AVX, AVX2]
memchr::arch::x86_64::memchr::count_raw::find_avx2 [AVX, AVX2]
_RNvNvNtNtNt<rust-hash>6memchr4arch6x86_646memchr10memchr_raw6detect [AVX, AVX2]
_RNvNvNtNtNt<rust-hash>6memchr4arch6x86_646memchr11memchr2_raw6detect [AVX, AVX2]
_RNvNvNtNtNt<rust-hash>6memchr4arch6x86_646memchr11memchr3_raw6detect [AVX, AVX2]
Expand All @@ -850,6 +851,15 @@ _RNvNvNtNtNt<rust-hash>6memchr4arch6x86_646memchr11memchr3_raw6detect [AVX, AVX
blake2b_simd::avx2::compress1_loop [AVX, AVX2]


# ----------------------------------------------------------------------------
# Rust sha2 SHA-NI (via p256 → bun_sigstore, publish --provenance). Gate:
# cpufeatures::new!(shani_cpuid, "sha", "sse2", "ssse3", "sse4.1") in
# sha2::sha256::x86::compress — falls back to soft::compress.
# (1 symbol)
# ----------------------------------------------------------------------------
sha2::sha256::x86::digest_blocks [SHA]


# ----------------------------------------------------------------------------
# MSVC STL vectorized algorithms. Gate: __isa_available.
# (14 symbols)
Expand Down
12 changes: 11 additions & 1 deletion scripts/verify-baseline-static/allowlist-x64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ _RNvNtNtNtNtNt<rust-hash>17compiler_builtins4math9libm_math4arch3x863fma13fma_wi

# ----------------------------------------------------------------------------
# Rust memchr AVX2 (via lolhtml deps). Gate: is_x86_feature_detected!.
# (11 symbols)
# (12 symbols)
# ----------------------------------------------------------------------------
_RNvMNtNtNtNt<rust-hash>6memchr4arch6x86_644avx26memchrNtB2_3One13find_raw_avx2 [AVX, AVX2]
_RNvMNtNtNtNt<rust-hash>6memchr4arch6x86_644avx26memchrNtB2_3One14rfind_raw_avx2 [AVX, AVX2]
Expand All @@ -960,6 +960,7 @@ _RNvNvNtNtNt<rust-hash>6memchr4arch6x86_646memchr10memchr_raw9find_avx2
_RNvNvNtNtNt<rust-hash>6memchr4arch6x86_646memchr11memchr2_raw9find_avx2 [AVX, AVX2]
_RNvNvNtNtNt<rust-hash>6memchr4arch6x86_646memchr11memchr3_raw9find_avx2 [AVX, AVX2]
_RNvNvNtNtNt<rust-hash>6memchr4arch6x86_646memchr11memrchr_raw9find_avx2 [AVX, AVX2]
_RNvNvNtNtNt<rust-hash>6memchr4arch6x86_646memchr9count_raw9find_avx2 [AVX, AVX2]
Comment thread
robobun marked this conversation as resolved.
# packedpair::Finder — only constructed when Finder::with_pair() sees avx2 in
# is_x86_feature_detected!(); the *_impl fns are #[target_feature(enable="avx2")]
# and only reached via that constructed Finder.
Expand All @@ -976,6 +977,15 @@ _RNvMNtNtNtNt<rust-hash>6memchr4arch6x86_644avx210packedpairNtB2_6Finder19find_p
_RNvNt<rust-hash>12blake2b_simd4avx214compress1_loop [AVX, AVX2]


# ----------------------------------------------------------------------------
# Rust sha2 SHA-NI (via p256 → bun_sigstore, publish --provenance). Gate:
# cpufeatures::new!(shani_cpuid, "sha", "sse2", "ssse3", "sse4.1") in
# sha2::sha256::x86::compress — falls back to soft::compress.
# (1 symbol)
# ----------------------------------------------------------------------------
_RNvNtNt<rust-hash>4sha26sha2563x8613digest_blocks [SHA]


# ----------------------------------------------------------------------------
# Bun.Image highway kernels (image_resize.cpp). Gate: HWY_DYNAMIC_DISPATCH ->
# hwy::SupportedTargets() via CPUID. Same gate as the highway_strings block.
Expand Down
26 changes: 26 additions & 0 deletions src/install/PackageManager/CommandLineArguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,15 @@ static PUBLISH_PARAMS: &[ParamType] = concat_params![
clap::param!(
"--tolerate-republish Don't exit with code 1 when republishing over an existing version number"
),
clap::param!(
"--provenance Generate a signed provenance statement (GitHub Actions / GitLab CI only)"
),
clap::param!(
"--no-provenance Do not generate a provenance statement"
),
clap::param!(
"--provenance-file <STR> Path to an externally-generated Sigstore provenance bundle to attach"
),
]
];

Expand Down Expand Up @@ -1175,6 +1184,23 @@ Full documentation is available at <magenta>https://bun.com/docs/cli/why<r>.
}

cli.tolerate_republish = args.flag(b"--tolerate-republish");

// `bun_clap::flag()` has no argument positions, so npm's last-flag-wins is not reproducible; both flags together is an error.
match (args.flag(b"--provenance"), args.flag(b"--no-provenance")) {
(true, true) => {
Output::err_generic(
"--provenance and --no-provenance cannot be used together",
(),
);
Global::crash();
}
(true, false) => cli.publish_config.provenance = Some(true),
(false, true) => cli.publish_config.provenance = Some(false),
(false, false) => {}
}
if let Some(path) = args.option(b"--provenance-file") {
cli.publish_config.provenance_file = path;
}
}

// link and unlink default to not saving, all others default to
Expand Down
10 changes: 10 additions & 0 deletions src/install/PackageManager/PackageManagerOptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,10 @@ pub struct PublishConfig {
pub otp: &'static [u8],
pub auth_type: Option<AuthType>,
pub tolerate_republish: bool,
/// `None` = neither `--provenance` flag nor `publishConfig.provenance` set; `NPM_CONFIG_PROVENANCE` is consulted at publish time.
pub provenance: Option<bool>,
/// `--provenance-file <path>`: attach this pre-built bundle instead of generating one.
pub provenance_file: &'static [u8],
}

#[derive(Copy, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -862,6 +866,12 @@ impl Options {
self.publish_config.auth_type = Some(auth_type);
}
self.publish_config.tolerate_republish = cli.tolerate_republish;
if let Some(prov) = cli.publish_config.provenance {
self.publish_config.provenance = Some(prov);
}
if !cli.publish_config.provenance_file.is_empty() {
self.publish_config.provenance_file = cli.publish_config.provenance_file;
}

if !cli.ca.is_empty() {
self.ca = cli.ca.iter().map(|s| Box::<[u8]>::from(*s)).collect();
Expand Down
1 change: 1 addition & 0 deletions src/runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ bun_safety.workspace = true
bun_semver.workspace = true
bun_semver_jsc.workspace = true
bun_sha_hmac.workspace = true
bun_sigstore.workspace = true
bun_shell_parser.workspace = true
bun_simdutf_sys.workspace = true
bun_sourcemap.workspace = true
Expand Down
5 changes: 5 additions & 0 deletions src/runtime/cli/pack_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1952,6 +1952,11 @@ pub(crate) fn pack<const FOR_PUBLISH: bool>(
};
}
}
if ctx.manager.options.publish_config.provenance.is_none() {
if let Some(prov) = config.get(b"provenance").and_then(|e| e.as_bool()) {
ctx.manager.options.publish_config.provenance = Some(prov);
}
}
}

// maybe otp
Expand Down
Loading
Loading