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
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ same for the completion scripts.
## Compatibility and the changelog

Command names, flags, the two output modes and the exit codes are promises;
the Mapbox APIs' own response bodies are not. The rules are in
[CONTRIBUTING.md](CONTRIBUTING.md#compatibility).
the Mapbox APIs' own response bodies, and commands marked beta, are not. The
rules are in [CONTRIBUTING.md](CONTRIBUTING.md#compatibility).

[CHANGELOG.md](CHANGELOG.md) is written by hand, newest first, because the
commit subject rarely explains why a change matters. A user-visible change
Expand Down
39 changes: 26 additions & 13 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,26 @@ What changed, and what it means for scripts that already use this tool.
Newest first, written by hand — the commit subject rarely explains why a
change matters.

Versions follow [semantic versioning](https://semver.org/). Pre-1.0 rule:
while the version starts with `0.`, a breaking change raises the minor
number (`0.1.0` → `0.2.0`); everything else raises the patch. What counts as
breaking is [written down in CONTRIBUTING.md](CONTRIBUTING.md#compatibility) — briefly,
command names, flags, the two output modes and the exit codes are promises;
the Mapbox APIs' own response bodies are not.
Versions follow [semantic versioning](https://semver.org/): a breaking
change raises the major number (`1.0.0` → `2.0.0`), a new feature the minor,
and a fix the patch. Before 1.0, a breaking change raised the minor number
instead. What counts as breaking is [written down in
CONTRIBUTING.md](CONTRIBUTING.md#compatibility) — briefly, command names,
flags, the two output modes and the exit codes are promises; the Mapbox APIs'
own response bodies, and commands marked beta, are not.

Cutting a release adds a `## <version> - <date>` heading below
`## Unreleased`, which stays in place so the next change has somewhere to go.
`tests/changelog.rs` fails while `Cargo.toml` names a version with no such
heading.

Dev-channel builds (`v0.1.3-dev.<sha>`) are published straight from a branch
that may never merge. They are not releases and are not listed here.

## Unreleased

## 1.0.0 - 2026-10-22

- New `mapbox report "<message>"` sends feedback about the CLI itself to
the Mapbox CLI team, with the CLI's version and OS appended. It is filed
under Mapbox's account, not yours. It is sent with the CLI's own token,
Expand Down Expand Up @@ -330,13 +335,12 @@ that may never merge. They are not releases and are not listed here.
only part of this that makes a request — the same precedent
`auth whoami --verify` sets.

- A native `aarch64-pc-windows-msvc` build. Windows on Arm ran the x64 build
under emulation before this — including inside a VM on Apple Silicon, the
larger of the two populations this serves — which `install.ps1` already
said out loud and now no longer has reason to. `install.ps1` already asked
the manifest for this target before falling back to the x64 one, and
`.cargo/config.toml` already named it, so publishing the artifact was the
whole client-side change.
- A native `aarch64-pc-windows-msvc` build. Windows on Arm, including in a
VM on Apple Silicon, ran the x64 build under emulation before this, which
`install.ps1` already said out loud and now no longer has reason to.
`install.ps1` already asked the manifest for this target before falling
back to the x64 one, and `.cargo/config.toml` already named it, so
publishing the artifact was the whole client-side change.

- `install.sh`/`install.ps1` now document a convention for `MAPBOX_CLI_INSTALL_SOURCE`
when a coding agent invokes the installer on someone's behalf: `agent-<name>`
Expand All @@ -346,6 +350,15 @@ that may never merge. They are not releases and are not listed here.
which would have collapsed `agent/claude-code` into `agentclaude-code` and
lost the separator. Comment-only: neither installer's behavior changed.

- `rustls-webpki` moved to 0.103.16 and `webpki-roots` to 1.0.10, fixing
[RUSTSEC-2026-0382](https://rustsec.org/advisories/RUSTSEC-2026-0382) and
[RUSTSEC-2026-0381](https://rustsec.org/advisories/RUSTSEC-2026-0381)
(CVE-2026-111943): certificate verification could accept a path through
distrusted emSign intermediates, whose private keys are now public. Both
are reached through `reqwest`, so every HTTPS request this CLI makes used
the affected versions; nothing in the crate itself had to change. Fixed in
[mapbox/mapbox-cli#106](https://github.com/mapbox/mapbox-cli/pull/106).

## 0.3.0 - 2026-09-22

### Added
Expand Down
10 changes: 7 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,17 @@ and data-flow diagram (OAuth login, credential storage, API requests).

## Compatibility

While this is `0.x`, a breaking change bumps the minor version
(`0.1.5` → `0.2.0`); everything else bumps the patch. From 1.0 on, plain
[semver](https://semver.org/). Breaking: a command/flag removed, renamed,
Versions follow [semver](https://semver.org/): a breaking change bumps the
major version (`1.4.2` → `2.0.0`), a new feature the minor, and a fix the
patch. Breaking: a command/flag removed, renamed,
or given a new default; an exit code or stdout/stderr change; a `--schema`
field removed or repurposed. Not breaking: new commands, new API response
fields, new `--schema` fields, and any wording.

A command marked beta is outside this promise until the label is removed:
it says so in its help and on every run, and it may change or be removed in
any release.

Deprecated commands and endpoints print a warning before the request goes
out, and are marked `[deprecated]` in `--help` and `--schema`.

Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mapbox-cli"
version = "0.3.0"
version = "1.0.0"
edition = "2021"
description = "A command-line interface for Mapbox APIs, with commands generated at build time from OpenAPI specs."
repository = "https://github.com/mapbox/mapbox-cli"
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ taking the newest, with or without the leading `v`, so the version
`mapbox --version` prints can be pasted straight in:

```sh
curl -fsSL https://cli.mapbox.com/install.sh | MAPBOX_CLI_VERSION=0.3.0 sh
curl -fsSL https://cli.mapbox.com/install.sh | MAPBOX_CLI_VERSION=1.0.0 sh
```

```powershell
$env:MAPBOX_CLI_VERSION = '0.3.0'; irm https://cli.mapbox.com/install.ps1 | iex
$env:MAPBOX_CLI_VERSION = '1.0.0'; irm https://cli.mapbox.com/install.ps1 | iex
```

Both scripts put the install directory on your `PATH`: `install.sh` adds a
Expand Down Expand Up @@ -139,7 +139,7 @@ Six targets are published: `aarch64-apple-darwin`, `x86_64-apple-darwin`,
then extract:

```sh
version=v0.3.0
version=v1.0.0
file=mapbox-${version}-aarch64-apple-darwin.tar.gz

curl -fsSLO "https://cli.mapbox.com/${version}/${file}"
Expand All @@ -154,7 +154,7 @@ On Windows the archive is a `.zip`, and PowerShell can read the manifest
directly:

```powershell
$version = 'v0.3.0'
$version = 'v1.0.0'
$target = 'x86_64-pc-windows-msvc'

$manifest = Invoke-RestMethod "https://cli.mapbox.com/$version/manifest.json"
Expand Down
45 changes: 45 additions & 0 deletions tests/changelog.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! Holds CHANGELOG.md to the version in `Cargo.toml`.
//!
//! A release bumps the version and moves the `## Unreleased` entries under a
//! `## <version> - <date>` heading in the same commit. Nothing in the release
//! pipeline reads the changelog, so a tag cut from a commit that bumped the
//! version but skipped the heading would ship with every entry still under
//! Unreleased. Between releases the version names the last one, whose heading
//! is already there, so this only bites on the commit that bumps it.

/// The heading's date is checked for shape only. Whether it is the day the
/// release actually went out is not something a test can know.
fn is_iso_date(text: &str) -> bool {
let bytes = text.as_bytes();
bytes.len() == 10
&& bytes.iter().enumerate().all(|(i, b)| match i {
4 | 7 => *b == b'-',
_ => b.is_ascii_digit(),
})
}

#[test]
fn the_current_version_has_a_dated_changelog_heading() {
let version = env!("CARGO_PKG_VERSION");
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/CHANGELOG.md");
let changelog = std::fs::read_to_string(path).expect("read CHANGELOG.md");
let prefix = format!("## {version} - ");
let found = changelog
.lines()
.filter_map(|line| line.strip_prefix(&prefix))
.any(is_iso_date);
assert!(
found,
"Cargo.toml says {version}, but CHANGELOG.md has no `## {version} - YYYY-MM-DD` \
heading. A version bump moves the Unreleased entries under that heading in the \
same commit."
);
}

#[test]
fn is_iso_date_takes_only_that_shape() {
assert!(is_iso_date("2026-09-22"));
assert!(!is_iso_date("<date>"));
assert!(!is_iso_date("2026-9-22"));
assert!(!is_iso_date("2026-09-22 (yanked)"));
}
Loading