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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.21.1] - 2026-09-05

### Fixed

- **`linear --version` reported `0.20.0` on a 0.21.0 install.** `__version__`
is bumped in the feature commit, not the release commit, and 0.21.0 shipped
without that bump — so every 0.21.0 install ran the right code and
self-reported the previous version. That silently breaks any "is this box up
to date?" check, including a fleet-wide `linear --version` sweep. No behavior
change beyond the version string.

## [0.21.0] - 2026-09-05

### Changed
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ Use the same shell contract whether you're typing or a subagent is: query the qu
Preferred (pinned tag + SHA-256 verify via `install.sh`):

```bash
curl -sSL https://raw.githubusercontent.com/phnx-labs/linear-cli/v0.21.0/install.sh | sh
curl -sSL https://raw.githubusercontent.com/phnx-labs/linear-cli/v0.21.1/install.sh | sh
```

Manual pin (same tag; no checksum — prefer `install.sh` above):

```bash
curl -o ~/.local/bin/linear https://raw.githubusercontent.com/phnx-labs/linear-cli/v0.21.0/linear
curl -o ~/.local/bin/linear https://raw.githubusercontent.com/phnx-labs/linear-cli/v0.21.1/linear
chmod +x ~/.local/bin/linear
```

Expand Down
4 changes: 2 additions & 2 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ set -eu
REPO="phnx-labs/linear-cli"
# Pin a release tag (not floating main). Override with LINEAR_CLI_VERSION /
# LINEAR_CLI_SHA256 only when you deliberately install a different revision.
VERSION="${LINEAR_CLI_VERSION:-v0.21.0}"
VERSION="${LINEAR_CLI_VERSION:-v0.21.1}"
# SHA-256 of the `linear` file at VERSION. Recomputed whenever VERSION bumps.
EXPECTED_SHA256="${LINEAR_CLI_SHA256:-d68fe508cb19460d0f2a517062a7a66646525539a11caedaa4a15ae5b3717cbe}"
EXPECTED_SHA256="${LINEAR_CLI_SHA256:-4055001dcdef84f21b30760a1a1e922dd4d0d7b4b9c936d3a6e5c4c143e7b465}"
URL="https://raw.githubusercontent.com/${REPO}/${VERSION}/linear"

pick_install_dir() {
Expand Down
2 changes: 1 addition & 1 deletion linear
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ _LOCK_CONTENDED_ERRNOS = tuple(
if e is not None
)

__version__ = "0.20.0"
__version__ = "0.21.1"

# Sentinel for "flag not supplied" — distinct from None, which means an explicit
# clear (e.g. `--project none`). Lets update pre-resolve a field once and pass
Expand Down
27 changes: 27 additions & 0 deletions test_linear.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
"""Regression tests for the `linear` CLI.

The CLI is intentionally dependency-free, so tests use only stdlib unittest.

Seeing a stale value for something you just edited in `linear`? macOS's system
python3 sets a global sys.pycache_prefix, and because `linear` has no .py
extension the cached name loses its separator (`linearcpython-39.pyc`), so the
usual invalidation is easy to miss when an edit doesn't change the file length.
Re-run with PYTHONDONTWRITEBYTECODE=1 before believing the result.
"""

import contextlib
Expand All @@ -10,6 +16,7 @@
import io
import json
import os
import re
import sys
import tempfile
import types
Expand Down Expand Up @@ -550,6 +557,26 @@ def test_bulk_error_survives_tabs_and_newlines_in_the_assign_value(self):
self.assertIn("matched no human", err)


class VersionMatchesChangelogTest(unittest.TestCase):
"""`__version__` lives in `linear` and is bumped in the feature commit, not
the release commit, so it is easy to forget — 0.21.0 shipped self-reporting
0.20.0, which made a fleet-wide `linear --version` sweep call every box
stale when it was in fact up to date."""

def test_version_matches_newest_released_changelog_entry(self):
changelog = Path(_HERE, "CHANGELOG.md").read_text()
# Released headings look like "## [0.21.1] - 2026-09-05";
# "## [Unreleased]" has no version and is skipped by the pattern.
versions = re.findall(r"^## \[(\d+\.\d+\.\d+)\]", changelog, re.MULTILINE)
self.assertTrue(versions, "no released version headings found in CHANGELOG.md")
self.assertEqual(
linear_cli.__version__, versions[0],
f"__version__ is {linear_cli.__version__!r} but the newest CHANGELOG "
f"entry is {versions[0]!r}. Bump __version__ in `linear` when you add "
f"the CHANGELOG entry, not at release time.",
)


class BulkTsvFieldTest(unittest.TestCase):
"""Bulk --from-file output is a tab-separated record. Titles come from the
caller's JSONL and from Linear, so neither may carry a raw tab/newline."""
Expand Down
Loading