Metadata-Version: 2.3
Name: gh-nfpm
Version: 0.1.0
Summary: Package GitHub releases using nFPM
Author: Fredrik Larsson
Author-email: Fredrik Larsson <pypi@fredriklarsson.dev>
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Environment :: Console
Classifier: Framework :: Pydantic :: 2
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: System :: Archiving :: Packaging
Classifier: Typing :: Typed
Classifier: Intended Audience :: System Administrators
Requires-Dist: githubkit>=0.15.5,<0.16
Requires-Dist: httpx>=0.28.1
Requires-Dist: jsonschema>=4.26.0
Requires-Dist: pydantic>2,<3
Requires-Dist: pydantic-settings[yaml]>=2.14.1
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: nfpm>=2.46.3 ; extra == 'nfpm'
Requires-Python: >=3.12
Provides-Extra: nfpm
Description-Content-Type: text/markdown

# gh-nfpm

Easily package GitHub releases using [nFPM](https://nfpm.goreleaser.com/).

Currently only supports building the latest GitHub release.

tl;dr You specify a GitHub repository, a list of release assets, and the nFPM
packaging configuration. gh-nfpm will download the matching assets from the
latest GitHub release in the repository and build an nFPM package for each
asset. You can build multiple package types for each asset.

## Configuration

The configuration is stored inside a YAML file called `gh-nfpm.yaml`.

### Repository and assets

The `repository` is specified with a string `organization/repository`, for
example this repository would be `nossralf/gh-nfpm`.

Asset matching supports literal matches or regular expressions. Currently only
`tar.gz` and `zip` assets are supported as package sources.

The shorthand format is literal matching, so:

```yaml
assets:
  - release.zip
  - release.tar.gz
```

would match release assets named exactly `release.zip` and `release.tar.gz`.

Regular expressions can be used for cases where the release asset contains a
version number:

```yaml
assets:
  - match:
      kind: regex
      pattern: ".*-aarch64-unknown-linux-musl.tar.gz$"
```

This would match `my-tool-3.14.15-aarch64-unknown-linux-musl.tar.gz`.

If the architecture cannot be deduced from the asset name, it can be specified
as part of the asset configuration, for example with a literal match (which
needs to use the verbose format when specifying an architecture):

```yaml
assets:
  - arch: all
    match:
      kind: literal
      pattern: architecture-independent-release.tar.gz
```

gh-nfpm will verify the digest of downloaded assets if one is present in the
GitHub API response. It will abort if a digest doesn't match.

### Packagers

The `packagers` list specifies which nFPM packagers should be run for each
asset. The supported values are `apk`, `archlinux`, `deb`, `ipk`, `msix`,
`rpm`, and `srpm`.

### Release cooldown

Release cooldown is supported by setting `cooldown`, either as an integer
representing seconds, or as an [ISO 8601
duration](https://en.wikipedia.org/wiki/ISO_8601#Durations), for example `P1W`
for one week, `P2D` for 2 days, or `PT12H` for 12 hours. The last _update_ of
the GitHub release is used when evaluating the cooldown.

### Other configuration options

- `token` sets the GitHub token used to interact with GitHub. By default,
  unauthenticated access is used. It can also be set via the environment
  variable `GHNFPM_TOKEN` to avoid hard-coding credentials in the configuration
  file.
- `nfpm_executable` can be set to specify the path to nFPM. By default gh-nfpm
  will assume that an `npfm` binary can be found via `$PATH`.

## nFPM configuration

The nFPM configuration is stored under a top-level key `nfpm` in the
`gh-nfpm.yaml` configuration file. The complete nFPM configuration schema is
supported and the content is validated with the nFPM JSON Schema.

The `version` and `arch` fields can be left out of the nFPM configuration and
will then be filled in based on the release name and architecture from the
release assets. If you do specify the version or the architecture, the value
you specify will always be used when building the package.

### Source paths

gh-nfpm will unpack the release assets by stripping off any leading directories
that don't contain files inside the asset, to avoid situations where e.g.
directories with version numbers would make static packaging configuration
impossible.

This means that if a release asset contains this directory structure:

```
.
└── release
    └── 0.13
        ├── completions
        │   └── tool.1
        └── tool
```

gh-nfpm will strip the leading `release/0.13` and unpack the asset like this:

```
.
├── completions
│   └── tool.1
└── tool
```

This enables specifying `tool` as the source path in nFPM's content
specification, instead of `release/0.13/tool`.

## Example

This is how you would build Debian packages (both x86-64 and AArch64) for
[uv](https://docs.astral.sh/uv/) with a 2 day release cooldown.

```yaml
repository: astral-sh/uv
cooldown: P2D
assets:
  - uv-x86_64-unknown-linux-musl.tar.gz
  - uv-aarch64-unknown-linux-musl.tar.gz
packagers:
  - deb

nfpm:
  name: uv
  platform: linux
  section: python
  description: |-
    An extremely fast Python package and project manager, written in Rust.
  homepage: https://docs.astral.sh/uv/
  maintainer: Mackenzie Maintainer <mackenzie@example.com>
  license: MIT or Apache-2.0

  contents:
    - src: uv
      dst: /usr/bin/uv
    - src: uvx
      dst: /usr/bin/uvx
```

## Usage

Create a gh-nfpm.yaml file, then run `uvx gh-nfpm`. The built packages will be
placed in the current directory.

If you don't have nFPM installed, you can run `uvx 'gh-nfpm[npfm]'` and nFPM
will be installed via the `nfpm`[Python
package](https://pypi.org/project/nfpm/). Be aware that the `npfm` PyPI package
is **not** provided by the nFPM team.
