Skip to content

feat(targets): add pkg-pacman target (Arch Linux AUR / PKGBUILD)#486

Open
forgou37 wants to merge 5 commits into
profullstack:masterfrom
forgou37:feat/pkg-pacman
Open

feat(targets): add pkg-pacman target (Arch Linux AUR / PKGBUILD)#486
forgou37 wants to merge 5 commits into
profullstack:masterfrom
forgou37:feat/pkg-pacman

Conversation

@forgou37
Copy link
Copy Markdown
Contributor

Closes #477

Adds the pkg-pacman target adapter for generating Arch Linux PKGBUILD and .SRCINFO files and publishing to the AUR.

What

  • Generates a valid PKGBUILD with correct variable quoting and array syntax
  • Generates the matching .SRCINFO metadata file (required by AUR)
  • Supports x86_64 / aarch64 / any architectures
  • Runtime depends, build makedepends, provides, conflicts
  • Default source URL derived from releaseRepo config
  • ship() pushes to AUR via SSH (requires AUR_SSH_KEY secret)
  • manualSetup guide for AUR account and SSH key setup
  • Full vitest test coverage (PKGBUILD + .SRCINFO content, dry-run ship)

Related

Part of #133 — implements sh1pt target sub-commands.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 30, 2026

Greptile Summary

Adds a new pkg-pacman target adapter that generates PKGBUILD and .SRCINFO files for Arch Linux AUR publishing. The file rendering and dry-run path work correctly, but there are two issues in the core logic that would break real-world usage.

  • .SRCINFO source URL is malformed: String.replace('$pkgver', version) only substitutes the first of two occurrences in the default URL template, leaving a literal $pkgver in the filename segment and producing an undownloadable source URL.
  • ship() silently pretends to succeed: the non-dry-run path returns a success result despite containing only a TODO comment — no git/SSH operations are performed — so callers will incorrectly believe the package was pushed to AUR.
  • The package() body in the generated PKGBUILD lacks a cd "$srcdir/$pkgname-$pkgver" step, which would cause install to fail for any tarball that extracts into a subdirectory (the common case for GitHub Release archives).

Confidence Score: 3/5

The build path (file generation) works and is well-tested, but the ship() function claims success without executing any AUR push, and .SRCINFO output will contain an unresolved shell variable in the source URL.

The .SRCINFO source URL bug means every generated metadata file will have a literal $pkgver in the download filename, making makepkg unable to fetch the source. The ship() stub returning success silently would mislead any CI pipeline into thinking an AUR release happened when nothing was pushed. Both issues affect the primary purpose of this adapter.

packages/targets/pkg-pacman/src/index.ts — the renderSRCINFO function and the ship() non-dry-run path both need fixes before this adapter produces valid output.

Important Files Changed

Filename Overview
packages/targets/pkg-pacman/src/index.ts Core adapter implementation — two confirmed bugs: .SRCINFO source URL retains a literal $pkgver in the filename segment, and ship() returns success without performing any actual AUR push.
packages/targets/pkg-pacman/src/index.test.ts Tests cover PKGBUILD and .SRCINFO generation and a dry-run ship, but do not assert the fully-resolved source URL in .SRCINFO (so the $pkgver bug would pass).
packages/targets/pkg-pacman/package.json Standard package manifest; no dev dependencies listed but the workspace likely hoists vitest. Looks fine.
packages/targets/pkg-pacman/README.md Documentation file; accurate and complete setup instructions.
packages/targets/pkg-pacman/tsconfig.json Minimal tsconfig extending the repo base — consistent with other target packages.

Sequence Diagram

sequenceDiagram
    participant User
    participant sh1pt
    participant PkgPacmanAdapter
    participant AUR

    User->>sh1pt: sh1pt promote build (pkg-pacman)
    sh1pt->>PkgPacmanAdapter: build(ctx, config)
    PkgPacmanAdapter->>PkgPacmanAdapter: renderPKGBUILD(config, version)
    PkgPacmanAdapter->>PkgPacmanAdapter: renderSRCINFO(config, version)
    PkgPacmanAdapter-->>sh1pt: artifact: PKGBUILD

    User->>sh1pt: sh1pt promote ship (pkg-pacman)
    sh1pt->>PkgPacmanAdapter: ship(ctx, config)
    alt dry-run
        PkgPacmanAdapter-->>sh1pt: id: dry-run
    else non-dry-run (NOT IMPLEMENTED)
        Note over PkgPacmanAdapter,AUR: TODO: git clone AUR repo, commit PKGBUILD+.SRCINFO, push via SSH
        PkgPacmanAdapter-->>sh1pt: silently returns success without pushing
    end

    User->>sh1pt: sh1pt status (pkg-pacman)
    sh1pt->>PkgPacmanAdapter: status(id)
    PkgPacmanAdapter-->>sh1pt: state: live, url
Loading

Reviews (1): Last reviewed commit: "feat(targets): add pkg-pacman tests" | Re-trigger Greptile

`\turl = ${config.url ?? 'https://sh1pt.com'}`,
`\tarch = ${arch}`,
`\tlicense = ${config.license ?? 'MIT'}`,
`\tsource = ${name}-${version}.tar.gz::${defaultSourceUrl(config).replace('$pkgver', version)}`,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 .SRCINFO source URL has only the first $pkgver substituted because String.replace(string, replacement) replaces only the first match. The default URL template contains two occurrences — one in the path segment (v$pkgver) and one in the filename (myapp-$pkgver-x86_64.tar.gz) — so the generated .SRCINFO will contain a literal $pkgver in the filename part, producing an invalid source URL that makepkg cannot download.

Suggested change
`\tsource = ${name}-${version}.tar.gz::${defaultSourceUrl(config).replace('$pkgver', version)}`,
`\tsource = ${name}-${version}.tar.gz::${defaultSourceUrl(config).replace(/\$pkgver/g, version)}`,

Comment on lines +117 to +130
async ship(ctx, config) {
const version = ctx.version.replace(/^v/, '');
ctx.log(`push ${config.pkgname} v${version} to AUR`);

if (ctx.dryRun) return { id: 'dry-run' };

// TODO: push updated PKGBUILD + .SRCINFO to the AUR git remote
// AUR URL: ssh://aur@aur.archlinux.org/<pkgname>.git
// Requires AUR_SSH_KEY from ctx.secret('AUR_SSH_KEY')
return {
id: `${config.pkgname}@${version}`,
url: `https://aur.archlinux.org/packages/${config.pkgname}`,
};
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 ship() silently returns success without doing anything

The non-dry-run path falls through to return { id, url } as if the package was published, but no actual git operations are performed — the AUR push is entirely unimplemented (the TODO comment confirms this). Any caller or CI pipeline will receive a successful result and believe the package is live on AUR when nothing was pushed. At minimum the stub should throw a NotImplementedError or log a clear warning so users are not silently misled into thinking a release happened.

Comment on lines +68 to +71
'package() {',
` install -Dm755 "${name}" "\${pkgdir}/usr/bin/${name}"`,
` install -Dm644 LICENSE "\${pkgdir}/usr/share/licenses/${name}/LICENSE" 2>/dev/null || true`,
'}',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 install -Dm755 "${name}" looks for the binary in the current directory at the time package() runs. makepkg changes into $srcdir before calling package(), and most GitHub Release tarballs extract into a subdirectory (e.g. myapp-3.0.1/). Without a cd step the binary won't be found and makepkg will fail. Referencing $srcdir/<name>-$pkgver/$name (or better, searching within $srcdir) is the standard pattern.

Suggested change
'package() {',
` install -Dm755 "${name}" "\${pkgdir}/usr/bin/${name}"`,
` install -Dm644 LICENSE "\${pkgdir}/usr/share/licenses/${name}/LICENSE" 2>/dev/null || true`,
'}',
'package() {',
` cd "\${srcdir}/${name}-\${pkgver}"`,
` install -Dm755 "${name}" "\${pkgdir}/usr/bin/${name}"`,
` install -Dm644 LICENSE "\${pkgdir}/usr/share/licenses/${name}/LICENSE" 2>/dev/null || true`,
'}',

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant