Metadata-Version: 2.5
Name: newertag
Version: 0.2.1
Summary: Check running container images for newer stable tags
Project-URL: Homepage, https://github.com/johe37/newertag
Project-URL: Repository, https://github.com/johe37/newertag
Project-URL: Issues, https://github.com/johe37/newertag/issues
Author: Jonathan H.
Keywords: container,docker,registry,tags,version
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: System Administrators
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.9
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# newertag

[![PyPI](https://img.shields.io/pypi/v/newertag.svg)](https://pypi.org/project/newertag/)
[![Python](https://img.shields.io/pypi/pyversions/newertag.svg)](https://pypi.org/project/newertag/)

Check whether pinned container images have a newer stable tag.

`newertag` looks at the tag you are already using — from a running container
today, or from an image you pass in later — and asks the registry for newer
stable releases in the same version family.

It prefers false negatives over false positives. Pre-release tags (`latest`,
`nightly`, `rc`, …) are ignored. Calendar versions and ordinary semantic
versions are not mixed. Packaging suffixes such as linuxserver `-ls43` stay
in-family.

## Requirements

- Python 3.9+
- [Docker](https://docs.docker.com/engine/)
- [skopeo](https://github.com/containers/skopeo)

There are no Python dependencies at runtime.

## Install

Install the published package from [PyPI](https://pypi.org/project/newertag/)
with [pipx](https://pipx.pypa.io/):

```bash
pipx install newertag
```

Or with pip:

```bash
pip install newertag
```

From this repository, in editable mode while developing:

```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
```

## Usage

Scan every running container:

```bash
newertag
```

```
CONTAINER               IMAGE                                     STATUS
qbittorrent             linuxserver/qbittorrent:5.2.3             up to date
home-assistant          homeassistant/home-assistant:2026.8.1     2026.9.0 available (minor)
```

```bash
newertag --verbose
newertag --help
```

Check one image. Without a tag, list the latest stable tags:

```bash
newertag jc21/nginx-proxy-manager
```

```
IMAGE   jc21/nginx-proxy-manager

Latest stable tags:
  2.15.1
  2.14.6
  2.14.5
  2.14.3
  2.14.2
```

With a tag, report whether a newer stable release exists:

```bash
newertag jc21/nginx-proxy-manager:2.12.3
```

```
IMAGE   jc21/nginx-proxy-manager:2.12.3
STATUS  2.15.1 available (minor)
```

The same entry point also works as a module:

```bash
python -m newertag
```

## Exit codes

| Code | Meaning |
| ---: | --- |
| 0 | No updates available |
| 1 | Updates available |
| 2 | Error |

## Development

```bash
pip install -e ".[dev]"
pytest
```

GitHub Actions runs the same suite on Python 3.9–3.13 for pushes to `main` /
`master` and for pull requests.

## Releasing

Publishing is tag-driven. Once the version you want is on `main` / `master`,
push a matching version tag (`0.2.1` or `v0.2.1`). That runs
`.github/workflows/publish.yml`, which checks that the tag matches the package
version, runs the tests, builds an sdist and wheel, and uploads them to
[PyPI](https://pypi.org/project/newertag/) with
[trusted publishing](https://docs.pypi.org/trusted-publishers/). No API token
is stored in the repository.

The package version is currently `0.2.1`. After this commit is on the default
branch, the next release is either of:

```bash
git tag 0.2.1
git push origin 0.2.1
```

```bash
git tag v0.2.1
git push origin v0.2.1
```

For later releases, bump `version` in `pyproject.toml` and `__version__` in
`src/newertag/__init__.py`, merge that to the default branch, then tag
`X.Y.Z` or `vX.Y.Z` and push the tag. A tag that does not match those versions
fails before upload.

### First-time PyPI setup

Do this once before pushing the first tag:

1. Create a GitHub Actions environment named `pypi` (Settings → Environments).
   Requiring a reviewer on that environment is recommended so a tag cannot
   publish without approval.
2. Register a pending trusted publisher at
   <https://pypi.org/manage/account/publishing/>:

   | Field | Value |
   | --- | --- |
   | PyPI project name | `newertag` |
   | Owner | `johe37` |
   | Repository | `newertag` |
   | Workflow name | `publish.yml` |
   | Environment name | `pypi` |

The first successful tag creates the PyPI project. After that, install with
`pipx install newertag` or `pip install newertag`.
