native-packages 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,192 @@
1
+ ---
2
+ title: Distribution recipes
3
+ description: Generate AUR and Homebrew recipes with release checksums, review downstream changes, and publish repository updates.
4
+ nav_order: 7
5
+ ---
6
+
7
+ # Distribution recipes
8
+
9
+ A distribution recipe tells a package manager where to get your app and how
10
+ to install or build it. Examples include an AUR `PKGBUILD`, a Homebrew formula
11
+ or cask, and a Gentoo ebuild.
12
+
13
+ native-packages fills in versions, download URLs, and checksums in templates
14
+ you keep with the app. It can then stage those files in a downstream Git
15
+ repository for review and publication.
16
+
17
+ This guide uses an AUR package as an example. The same asset and template
18
+ settings work for other recipe formats.
19
+
20
+ ## 1. Declare the release asset
21
+
22
+ Add an asset for the archive your recipe downloads:
23
+
24
+ ```yaml
25
+ release:
26
+ repository: your-name/hello
27
+ assets:
28
+ AMD64:
29
+ file: hello_@VERSION@_linux_amd64.tar.gz
30
+ local: dist/hello_@VERSION@_linux_amd64.tar.gz
31
+ ```
32
+
33
+ For local builds, native-packages hashes `local`. In release mode, it downloads
34
+ `file` from the configured release and verifies its entry in `checksums.txt`.
35
+ An explicit `url` can point elsewhere.
36
+
37
+ Each asset provides three values for templates: `@AMD64_FILE@`,
38
+ `@AMD64_URL@`, and `@AMD64_SHA256@`. Use uppercase names such as `AMD64`
39
+ or `MACOS` for asset keys.
40
+
41
+ ## 2. Write a template
42
+
43
+ Create `packaging/arch/hello-bin/PKGBUILD.in`:
44
+
45
+ ```sh
46
+ pkgname=hello-bin
47
+ pkgver=@VERSION@
48
+ pkgrel=@PKGREL@
49
+ pkgdesc='A small greeting application'
50
+ arch=('x86_64')
51
+ url='@UPSTREAM@'
52
+ license=('MIT')
53
+ depends=('glibc')
54
+ provides=('hello')
55
+ conflicts=('hello')
56
+ source=('@AMD64_URL@')
57
+ sha256sums=('@AMD64_SHA256@')
58
+
59
+ package() {
60
+ install -Dm755 hello "$pkgdir/usr/bin/hello"
61
+ install -Dm644 LICENSE "$pkgdir/usr/share/licenses/hello/LICENSE"
62
+ }
63
+ ```
64
+
65
+ This example expects the archive to contain `hello` and `LICENSE` at its root.
66
+ Use dependencies and metadata appropriate to your actual app.
67
+
68
+ Map the generated path to the template in `native-packages.yaml`:
69
+
70
+ ```yaml
71
+ templates:
72
+ arch/hello-bin/PKGBUILD: packaging/arch/hello-bin/PKGBUILD.in
73
+ ```
74
+
75
+ The left side is a path under the build's `recipes/` directory. The right side
76
+ is a source path relative to your configuration.
77
+
78
+ For paths matching `arch/<package>/PKGBUILD`, native-packages also generates
79
+ `.SRCINFO`, the package metadata used by AUR. This needs `makepkg` or working
80
+ Docker. Recipe archives need `tar` and `xz`.
81
+
82
+ ## 3. Generate and test the recipe
83
+
84
+ Build with your existing package targets and the new settings:
85
+
86
+ ```sh
87
+ native-packages build --version 1.2.3 --output dist/with-recipes
88
+ ```
89
+
90
+ Look in `dist/with-recipes/recipes/arch/hello-bin/` for `PKGBUILD` and `.SRCINFO`.
91
+ Review the rendered URLs, version, checksum, dependencies, and installation
92
+ paths. Test the recipe with the destination's normal tooling on a suitable
93
+ machine before publishing it.
94
+
95
+ A project that only generates recipes can use `targets: {}`. It still needs
96
+ `schema`, `tool`, `nfpm.name`, and the asset/template configuration.
97
+
98
+ ## 4. Configure a destination
99
+
100
+ Add the existing downstream repository under `repositories`:
101
+
102
+ ```yaml
103
+ repositories:
104
+ aur-bin:
105
+ group: aur
106
+ url: https://aur.archlinux.org/hello-bin.git
107
+ push_url: ssh://aur@aur.archlinux.org/hello-bin.git
108
+ branch: master
109
+ package_path: .
110
+ files:
111
+ arch/hello-bin/PKGBUILD: PKGBUILD
112
+ arch/hello-bin/.SRCINFO: .SRCINFO
113
+ version_file: PKGBUILD
114
+ version_pattern: '^pkgver=(\S+)'
115
+ publish: push
116
+ ```
117
+
118
+ Use your actual package repository and configure credentials for it. `files`
119
+ maps generated paths under `recipes/` to paths in the downstream repository.
120
+ `version_pattern` extracts the existing version so the tool can detect updates
121
+ and downgrades.
122
+
123
+ The `group` lets you operate on related destinations together. For example,
124
+ `aur` can select both a binary package and a source package.
125
+
126
+ ## 5. Stage, review, and publish
127
+
128
+ ```sh
129
+ native-packages repositories
130
+ native-packages stage aur dist/with-recipes/recipes
131
+ native-packages diff aur
132
+ native-packages publish aur
133
+ ```
134
+
135
+ `stage` prepares the update in an independent checkout under
136
+ `.cache/packaging/repos/`. `diff` shows what will change. `publish` commits and
137
+ pushes the staged update. Add `.cache/` to your application's `.gitignore`.
138
+
139
+ Each destination has its own checkout. Your app needs no Git submodules or
140
+ additional remotes. Updates touch the mapped package paths and preserve other
141
+ files; Gentoo updates also preserve older ebuilds and Manifest entries.
142
+
143
+ Check downstream state with:
144
+
145
+ ```sh
146
+ native-packages status
147
+ native-packages status aur --offline --json
148
+ ```
149
+
150
+ The offline form uses cached information. Normal status checks query upstream
151
+ repositories and open requests.
152
+
153
+ ## Homebrew formulae and casks
154
+
155
+ Keep a formula or cask template in your app, then map it through `templates`
156
+ and `repositories.files` just like the AUR example. A tap you own typically
157
+ uses `publish: push` and a destination named `homebrew`.
158
+
159
+ Use a formula for the appropriate command-line package or a cask for a native
160
+ app download. Your template owns the package manager's installation logic.
161
+ If a cask refers to a DMG created by this release, use
162
+ [deferred recipe generation](multi-platform.md#generate-recipes-after-packages-are-built)
163
+ so its checksum comes from the completed, signed image.
164
+
165
+ ## Submit a pull request or merge request
166
+
167
+ Use `publish: github-pr` or `publish: gitlab-mr` for a repository that accepts
168
+ contributions through review. Create the fork first and supply its URLs and
169
+ submission settings. The [repository reference](../_reference/configuration.md#repositories)
170
+ lists these fields.
171
+
172
+ Staging writes a starting description to `.cache/packaging/submissions/` and
173
+ prints its path. Edit it to describe the update and the checks you ran, then
174
+ publish that destination by name:
175
+
176
+ ```sh
177
+ native-packages diff community
178
+ native-packages publish community --body-file .cache/packaging/submissions/community.md
179
+ ```
180
+
181
+ The tool can reuse an existing open request. Successful submission means the
182
+ request exists; the upstream project still reviews and accepts it.
183
+
184
+ Use `publish: manual` with `notes` for destinations that need an external
185
+ process. The CLI reports those instructions rather than submitting an update.
186
+
187
+ ## Next steps
188
+
189
+ Once the process is tested, enable destination publication in
190
+ [GitHub Actions](github-actions.md#enable-aur-or-homebrew-publication).
191
+ For package files themselves, use [Publishing a release](publishing.md).
192
+ This tool does not host APT or DNF package indexes.
@@ -0,0 +1,184 @@
1
+ ---
2
+ title: Getting started
3
+ description: Install native-packages and build a DEB and RPM from a compiled Linux application.
4
+ nav_order: 1
5
+ ---
6
+
7
+ # Getting started
8
+
9
+ By the end of this guide, you will have a DEB and an RPM containing your app,
10
+ ready to test on Linux.
11
+
12
+ We will package an application called `hello`. You can follow along with your
13
+ own compiled executable, or build the tiny example below.
14
+
15
+ ## 1. Install the tools
16
+
17
+ You need Ruby 3.2 or later. Install the version used by these guides:
18
+
19
+ ```sh
20
+ gem install native-packages --version 0.7.0
21
+ ```
22
+
23
+ For Linux packages, install **nFPM 2.47.0**, the helper native-packages uses to
24
+ write package files. Download the matching build from the
25
+ [nFPM release](https://github.com/goreleaser/nfpm/releases/tag/v2.47.0)
26
+ and put `nfpm` on your `PATH`. If you already use Go, you can install it with:
27
+
28
+ ```sh
29
+ go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.47.0
30
+ export PATH="$(go env GOPATH)/bin:$PATH"
31
+ ```
32
+
33
+ You also need `readelf` to inspect Linux binaries and `bsdtar` to unpack
34
+ archives. On Debian or Ubuntu:
35
+
36
+ ```sh
37
+ sudo apt-get install binutils libarchive-tools
38
+ ```
39
+
40
+ Other distributions provide these through their binutils and libarchive
41
+ packages. The [reusable GitHub Actions workflow](github-actions.md) installs
42
+ the packaging tools for you.
43
+
44
+ ## 2. Prepare your application
45
+
46
+ Start in your application's root directory. This example expects a Linux
47
+ x86-64 executable at `dist/hello`, built against glibc.
48
+
49
+ If you have a C compiler on an x86-64 Linux system using glibc, you can create
50
+ a sample in a new directory:
51
+
52
+ ```sh
53
+ mkdir hello-packaging
54
+ cd hello-packaging
55
+ mkdir dist
56
+ cat > hello.c <<'C'
57
+ #include <stdio.h>
58
+ int main(void) {
59
+ puts("Hello from a native package!");
60
+ return 0;
61
+ }
62
+ C
63
+ cc -o dist/hello hello.c
64
+ ```
65
+
66
+ For your own app, run its usual build command instead and note where it puts
67
+ the executable. Packaging starts from those built files.
68
+
69
+ ## 3. Create a configuration
70
+
71
+ Generate a starting point:
72
+
73
+ ```sh
74
+ native-packages init --name hello --formats deb,rpm
75
+ ```
76
+
77
+ Open the generated `native-packages.yaml` and replace its contents with:
78
+
79
+ ```yaml
80
+ schema: 1
81
+ tool:
82
+ version: '0.7.0'
83
+ nfpm: '2.47.0'
84
+
85
+ nfpm:
86
+ name: hello
87
+ description: A small greeting application
88
+ maintainer: Your Name <you@example.com>
89
+ license: MIT
90
+ contents:
91
+ - src: '@PAYLOAD@/hello'
92
+ dst: /usr/bin/hello
93
+ file_info:
94
+ mode: 0755
95
+
96
+ targets:
97
+ linux-amd64:
98
+ platform: linux
99
+ arch: amd64
100
+ libc: glibc
101
+ formats: [deb, rpm]
102
+ input:
103
+ kind: file
104
+ local: dist/hello
105
+ ```
106
+
107
+ Use your own maintainer details and your app's actual license. There are three
108
+ parts to understand:
109
+
110
+ - **`tool`** selects the tool versions, so everyone builds with the same setup.
111
+ - **`nfpm`** describes the package: its name, metadata, and installed files.
112
+ `src` is the file to include; `dst` is where it will be installed.
113
+ - **`targets`** describes the build inputs and output formats. `amd64` means
114
+ x86-64, and `glibc` is the C library used by this example's executable.
115
+
116
+ `@PAYLOAD@` is a temporary copy of your input. Here, it contains `hello`.
117
+ The destination `/usr/bin/hello` is inside the package; building does not
118
+ install it on your machine.
119
+
120
+ The default generated configuration expects an archive. We set `kind: file`
121
+ because this example supplies one executable. For ARM64, use `arch: arm64`
122
+ and an ARM64 build of your app. See [input types and targets](building-packages.md).
123
+
124
+ ## 4. Check and build
125
+
126
+ Check the configuration and tools:
127
+
128
+ ```sh
129
+ native-packages doctor
130
+ ```
131
+
132
+ If anything is missing, the command reports what to fix. Once it succeeds,
133
+ build version 1.2.3:
134
+
135
+ ```sh
136
+ native-packages build --version 1.2.3
137
+ ```
138
+
139
+ The command checks your executable's architecture and linked libraries, then
140
+ creates both packages. You should see:
141
+
142
+ ```text
143
+ dist/packages/1.2.3/
144
+ packages/
145
+ linux-amd64/
146
+ deb/ # your .deb file
147
+ rpm/ # your .rpm file
148
+ recipes/
149
+ release.json
150
+ build.json
151
+ packaging-checksums.txt
152
+ ```
153
+
154
+ `build.json` records the inputs, outputs, and checks performed.
155
+ `packaging-checksums.txt` lists file hashes so changes can be detected.
156
+ Keep the whole directory if you plan to publish the build later.
157
+
158
+ To try again after changing your app or configuration, choose a new output
159
+ directory:
160
+
161
+ ```sh
162
+ native-packages build --version 1.2.3 --output dist/second-build
163
+ ```
164
+
165
+ ## 5. Test the package
166
+
167
+ On a disposable Debian or Ubuntu machine, copy the DEB there and install it:
168
+
169
+ ```sh
170
+ sudo apt install ./hello_1.2.3_amd64.deb
171
+ hello
172
+ sudo apt remove hello
173
+ ```
174
+
175
+ Use the filename produced by your build. For the sample, `hello` prints
176
+ `Hello from a native package!`. For your own app, also test startup, upgrades,
177
+ and removal on each distribution you support. A successful package build
178
+ checks the files; installation testing checks how the app behaves.
179
+
180
+ ## Where to go next
181
+
182
+ Continue with [Building packages](building-packages.md) to add icons,
183
+ configuration files, dependencies, and more architectures. When your package
184
+ is ready, follow [Publishing a release](publishing.md).
@@ -0,0 +1,146 @@
1
+ ---
2
+ title: GitHub Actions
3
+ description: Add package building and optional publication to your application's GitHub Actions workflow.
4
+ nav_order: 4
5
+ ---
6
+
7
+ # GitHub Actions
8
+
9
+ The reusable workflow installs the tools, builds your packages, and saves the
10
+ result as an Actions artifact. It can also upload packages to an existing
11
+ GitHub release.
12
+
13
+ Before adding it, commit `native-packages.yaml` and check that you can
14
+ [build locally](getting-started.md).
15
+
16
+ ## Package an existing release
17
+
18
+ Add this job under `jobs` in your application's release workflow. In this
19
+ example, the existing `release` job uploads the application's binary archives
20
+ and `checksums.txt` to a release matching the Git tag.
21
+
22
+ ```yaml
23
+ packaging:
24
+ needs: release
25
+ permissions:
26
+ contents: write
27
+ uses: crmne/native-packages/.github/workflows/package.yml@v0.7.0
28
+ with:
29
+ version: ${{ github.ref_name }}
30
+ publish: true
31
+ secrets: inherit
32
+ ```
33
+
34
+ Set `needs` to your actual release job's name. Use this example in a tag-based
35
+ release workflow, where `github.ref_name` is a version such as `v1.2.3`.
36
+ For other triggers, pass the release version explicitly.
37
+
38
+ The configuration must include `release.repository` and a `release_asset`
39
+ for each selected target. See [Publishing a release](publishing.md).
40
+
41
+ Use the same native-packages release for the workflow and `tool.version`.
42
+ For an immutable workflow reference, replace `v0.7.0` with that release's
43
+ full commit SHA.
44
+
45
+ ## Build without publishing
46
+
47
+ Set `publish: false` to build and upload the `native-packages` Actions
48
+ artifact without attaching anything to the GitHub release. This is useful
49
+ while you test the workflow.
50
+
51
+ With no `version`, the reusable workflow only validates the configuration:
52
+
53
+ ```yaml
54
+ name: Check packaging
55
+ on: [pull_request]
56
+ permissions:
57
+ contents: read
58
+ jobs:
59
+ packaging:
60
+ uses: crmne/native-packages/.github/workflows/package.yml@v0.7.0
61
+ ```
62
+
63
+ Validation does not compile the app or check that future release inputs exist.
64
+
65
+ ## Use files from an Actions artifact
66
+
67
+ If a preceding job uploads your compiled app as an Actions artifact, use
68
+ `source-artifact` instead of downloading inputs from a GitHub release:
69
+
70
+ ```yaml
71
+ packaging:
72
+ needs: build
73
+ permissions:
74
+ contents: write
75
+ uses: crmne/native-packages/.github/workflows/package.yml@v0.7.0
76
+ with:
77
+ version: '1.2.3'
78
+ source-artifact: linux-binaries
79
+ source-directory: dist
80
+ publish: false
81
+ ```
82
+
83
+ Here, the existing `build` job must upload an artifact named `linux-binaries`.
84
+ The workflow extracts it under `dist`. Its filenames and directory structure
85
+ must match your targets' `input.local` paths. This uses local build mode,
86
+ which runs any configured `before_build` hook.
87
+
88
+ ## Select Linux targets in a shared configuration
89
+
90
+ The reusable workflow runs on Linux. If your configuration also has DMG or
91
+ Inno targets, select the Linux targets explicitly:
92
+
93
+ ```yaml
94
+ with:
95
+ version: ${{ github.ref_name }}
96
+ targets: linux-amd64,linux-arm64
97
+ publish: true
98
+ ```
99
+
100
+ The workflow passes the same target selection to build and publication.
101
+ It requires every format declared for those targets. An empty selection
102
+ means all configured targets.
103
+
104
+ Build DMG and Inno targets in your own macOS and Windows jobs with the CLI.
105
+ See [Building across platforms](multi-platform.md) for combining their outputs
106
+ and generating recipes after all packages are available.
107
+
108
+ ## Workflow inputs
109
+
110
+ | Input | Default | Purpose |
111
+ | --- | --- | --- |
112
+ | `version` | Empty | App version or tag. Empty means validate only. |
113
+ | `publish` | `false` | Upload packages to the existing release; enable configured downstream publishing. |
114
+ | `targets` | Empty | Comma-separated target IDs. Empty selects all targets. |
115
+ | `config` | Auto-discovered | Path to the configuration file. |
116
+ | `source-artifact` | Empty | Artifact containing local inputs. Empty uses GitHub release assets. |
117
+ | `source-directory` | `dist` | Where to download that artifact, relative to the checkout. |
118
+
119
+ ## Enable AUR or Homebrew publication
120
+
121
+ First set up and test the [downstream destination](distribution-recipes.md).
122
+ Then configure these repository variables and secrets in your application's
123
+ GitHub repository:
124
+
125
+ | Destination | Repository variable | Secrets |
126
+ | --- | --- | --- |
127
+ | AUR group `aur` | `PUBLISH_AUR=true` | `AUR_SSH_KEY`, `AUR_KNOWN_HOSTS` |
128
+ | Destination or group `homebrew` | `PUBLISH_HOMEBREW=true` | `HOMEBREW_TAP_GITHUB_TOKEN` |
129
+
130
+ These steps run only with `publish: true`. The Homebrew token needs write
131
+ access to your tap; the AUR key needs access to the configured repositories.
132
+ Use `secrets: inherit` as in the release example, or pass the named secrets
133
+ explicitly. If another tool already publishes a destination, keep one
134
+ publisher responsible for it.
135
+
136
+ ## Multiple jobs and configurations
137
+
138
+ The reusable workflow gives different configuration paths and target
139
+ selections separate concurrency groups. If you are still using the old
140
+ `v0.5.0` workflow, serialize calls with `needs` or upgrade to avoid calls
141
+ interfering with one another.
142
+
143
+ When downloading build outputs from native jobs, preserve the entire build
144
+ directory, including hidden files in generated recipes. See
145
+ [Building across platforms](multi-platform.md) for the shared timestamp and
146
+ checkout requirements.
@@ -0,0 +1,153 @@
1
+ ---
2
+ title: Building across platforms
3
+ description: Build targets on their required hosts, combine the results, and generate distribution recipes once all packages are ready.
4
+ nav_order: 8
5
+ ---
6
+
7
+ # Building across platforms
8
+
9
+ When a release includes Linux packages, a DMG, and a Windows installer, each
10
+ build job can produce its own directory. **Aggregation** combines those
11
+ verified directories into one result you can publish.
12
+
13
+ This guide assumes your configuration already declares the targets. Use
14
+ [Building packages](building-packages.md) for Linux and
15
+ [macOS and Windows installers](native-recipes.md) for native targets.
16
+
17
+ ## Use the same release inputs
18
+
19
+ Every job must use the same configuration, app version, and build timestamp.
20
+ Check out the same commit with the same Git history depth on every host.
21
+ Set `SOURCE_DATE_EPOCH` to the same Unix timestamp in each job, normally the
22
+ release commit's timestamp.
23
+
24
+ For example, in a shell on Linux or macOS:
25
+
26
+ ```sh
27
+ export SOURCE_DATE_EPOCH="$(git show -s --format=%ct HEAD)"
28
+ ```
29
+
30
+ In PowerShell on Windows:
31
+
32
+ ```powershell
33
+ $env:SOURCE_DATE_EPOCH = git show -s --format=%ct HEAD
34
+ ```
35
+
36
+ In GitHub Actions, use `fetch-depth: 0` on each checkout so Git-derived recipe
37
+ values agree. Native packaging scripts should respect the shared timestamp
38
+ where their tools support it.
39
+
40
+ ## Build each target on its host
41
+
42
+ For a project with exactly these three targets, run the corresponding command
43
+ in each job:
44
+
45
+ ```sh
46
+ # Linux
47
+ native-packages build --version 1.2.3 --target linux-amd64 --output dist/linux
48
+
49
+ # macOS
50
+ native-packages build --version 1.2.3 --target macos-arm64 --output dist/macos
51
+
52
+ # Windows
53
+ native-packages build --version 1.2.3 --target windows-amd64 --output dist/windows
54
+ ```
55
+
56
+ Transfer the complete build directories to the machine that will combine
57
+ and publish them. Keep `build.json`, the package subdirectories, and any
58
+ recipes. Preserve hidden files such as `.SRCINFO` when uploading CI artifacts.
59
+
60
+ Then run from a checkout with the same configuration:
61
+
62
+ ```sh
63
+ native-packages aggregate dist/linux dist/macos dist/windows --output dist/complete
64
+ ```
65
+
66
+ The command checks hashes and rejects overlapping target/format outputs,
67
+ conflicting recipe files, and missing targets. The destination must be new.
68
+ The original build directories are preserved.
69
+
70
+ After your app's package tests pass:
71
+
72
+ ```sh
73
+ native-packages publish --from dist/complete --to github
74
+ ```
75
+
76
+ ## Generate recipes after packages are built
77
+
78
+ A Homebrew cask may need the checksum of the DMG produced by this very release.
79
+ In that case, **defer recipes**: build the packages first and render recipes
80
+ once the final files are available.
81
+
82
+ On each host, add `--defer-recipes`:
83
+
84
+ ```sh
85
+ native-packages doctor --target linux-amd64 --defer-recipes
86
+ native-packages build --version 1.2.3 --target linux-amd64 --defer-recipes --output dist/linux
87
+ native-packages build --version 1.2.3 --target macos-arm64 --defer-recipes --output dist/macos
88
+ native-packages build --version 1.2.3 --target windows-amd64 --defer-recipes --output dist/windows
89
+ ```
90
+
91
+ Each job still checks its selected targets and runs signing hooks, but skips
92
+ global recipe assets and recipe tools. AUR tooling is therefore needed only
93
+ on the finalization host.
94
+
95
+ Collect the results on Linux, along with any additional recipe assets, and run:
96
+
97
+ ```sh
98
+ native-packages aggregate dist/linux dist/macos dist/windows \
99
+ --finalize-recipes --output dist/complete
100
+ ```
101
+
102
+ The command verifies all targets, resolves asset hashes, generates the recipes
103
+ and recipe archive, and writes a completed build. You can then test and publish:
104
+
105
+ ```sh
106
+ native-packages publish --from dist/complete --to github,aur,homebrew
107
+ ```
108
+
109
+ Only name destinations you have configured. A deferred build cannot be
110
+ published directly, and ordinary and deferred build directories cannot be
111
+ mixed in one aggregate.
112
+
113
+ ## Connect a recipe asset to a built package
114
+
115
+ Declare the asset's `file` to match the native package's output filename:
116
+
117
+ ```yaml
118
+ assets:
119
+ MACOS:
120
+ file: hello-@TAG@-macos-arm64.dmg
121
+ ```
122
+
123
+ For version 1.2.3, the finalizer finds the verified package named
124
+ `hello-v1.2.3-macos-arm64.dmg`. Its hash includes signing and notarization.
125
+ A recipe can then use `@MACOS_URL@` and `@MACOS_SHA256@`.
126
+
127
+ A matching package takes precedence over an asset's `local` path. Package
128
+ filenames must be unique. Other assets, such as source or portable archives,
129
+ need their configured `local` files on the finalization host. Finalization
130
+ does not download those assets, even when the target builds used `--release`.
131
+
132
+ ## Requirements for finalization
133
+
134
+ All input directories must defer recipes and agree on configuration, version,
135
+ timestamp, tool versions, and recipe metadata. Include every configured target
136
+ and format. The finalizer needs `tar` and `xz` for recipe archives, and
137
+ `makepkg` or working Docker for AUR metadata.
138
+
139
+ A deferred target can use asset filenames and URLs, but it cannot use an
140
+ unknown asset hash such as `@MACOS_SHA256@` in its own input, package definition,
141
+ or hooks. Such a target needs an ordinary build with that asset already
142
+ available. Release downloads still require checksums when recipes are deferred.
143
+
144
+ Prerelease recipes cannot be finalized. See [Prereleases](prereleases.md)
145
+ for using a shared native configuration with stable recipes.
146
+
147
+ ## Publish Linux targets separately
148
+
149
+ If your app's own jobs already upload the native installers, you can use the
150
+ [reusable Linux workflow](github-actions.md#select-linux-targets-in-a-shared-configuration)
151
+ with `targets: linux-amd64,linux-arm64`. That workflow builds and publishes
152
+ exactly those complete targets. This is useful when you do not need a combined
153
+ release directory or deferred recipe finalization.