Skip to content

feat(targets): add pkg-pacman target (Arch custom repository)#477

Open
Alexander-Sorrell-IT wants to merge 3 commits into
profullstack:masterfrom
Alexander-Sorrell-IT:feat/target-pkg-pacman
Open

feat(targets): add pkg-pacman target (Arch custom repository)#477
Alexander-Sorrell-IT wants to merge 3 commits into
profullstack:masterfrom
Alexander-Sorrell-IT:feat/target-pkg-pacman

Conversation

@Alexander-Sorrell-IT
Copy link
Copy Markdown

Add pkg-pacman target — Arch custom repository (repo-add)

Implements the pkg-pacman distribution target — a custom Arch binary repo built with repo-add (this is not the AUR; pkg-aur covers that). Fills the README "Package managers → pacman" entry; mirrors the pkg-apt/pkg-dnf convention.

What's included

  • packages/targets/pkg-pacman/ — adapter, tests, package.json, tsconfig, README.
  • build() generates a real PKGBUILD (pkgver normalized — no -/:; shell-escaped pkgdesc/url) plus a pacman.conf [repo] snippet for consumers.
  • ship() is dry-run-safe and surfaces the exact makepkg + repo-add --sign commands; live publish throws not implemented rather than a false success.
  • Input hardening: assertValidNames() rejects pkgname outside Arch rules and repoName outside [A-Za-z0-9_-], closing PKGBUILD-syntax and pacman.conf [section] injection vectors; shell command args are quoted.
  • Registered in packages/cli/src/adapter-registry.ts; TARGETS.md row added (✅).

Tests

  • smokeTest + PKGBUILD/pacman.conf generation, pkgver normalization, shell-escaping, dry-run command surfacing, live-throw, bash -n syntax validation with hostile field values, and name-rejection cases.
  • typecheck clean; 8/8 tests pass; pnpm install --frozen-lockfile green.

No external CLI or secrets needed for build/test (dry-run only).

Adds the pacman distribution target — a custom Arch binary repo via repo-add
(NOT the AUR; pkg-aur covers that). Mirrors the pkg-apt/pkg-dnf convention.
- build() generates a real PKGBUILD (pkgver normalized: no '-'/':'; shell-escaped
  pkgdesc/url) + a pacman.conf [repo] snippet for consumers.
- ship() is dry-run-safe and surfaces makepkg + repo-add (--sign) commands; live
  publish throws not-implemented rather than a false success.
- Register pkg-pacman in cli adapter-registry; TARGETS.md row added.
- assertValidNames(): reject pkgname not matching Arch rules and repoName
  outside [A-Za-z0-9_-] — closes PKGBUILD syntax + pacman.conf [section]
  injection vectors (called from build() and ship()).
- Quote repo db / pkgfile / rsync dest in publishCommands.
- sha256sums via bashArray (escapes embedded quotes).
- ship() throws not-implemented immediately (no misleading secret check).
- Tests: bash -n syntax validation with hostile inputs + name-rejection cases.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 29, 2026

Greptile Summary

This PR adds the pkg-pacman distribution target adapter, which generates a valid PKGBUILD and a pacman.conf repo snippet for Arch custom binary repositories (via repo-add), and registers the new adapter in the CLI registry. Live publish is intentionally left unimplemented and throws, while dry-run surfaces the makepkg + repo-add commands for preview.

  • PKGBUILD generation (index.ts): normalizes pkgver (strips v, maps -/: to _), escapes pkgdesc/url/sourceUrl via shEscape, wraps array fields via bashArray, and validates pkgname, repoName, repoBaseUrl, and pkgrel via assertValidNames before writing any files.
  • Tests (index.test.ts): covers smoke, PKGBUILD generation, version normalization, hostile-value bash -n syntax validation, dry-run/live-throw path, and all rejection cases for the four validated fields — all previously raised injection concerns have been addressed in this revision.

Confidence Score: 5/5

This PR is safe to merge — it adds a self-contained new adapter with no changes to existing behaviour.

The adapter is fully isolated in a new package with no modifications to any existing adapter logic. All previously raised injection concerns (repoBaseUrl newline injection, unquoted pkgrel, misleading test description) have been addressed in this revision: assertValidNames now guards all four fields, and the test suite confirms both the happy paths and every rejection case with a bash -n proof for hostile inputs.

No files require special attention.

Important Files Changed

Filename Overview
packages/targets/pkg-pacman/src/index.ts Core adapter: PKGBUILD/pacman.conf generation with input validation (pkgname, repoName, repoBaseUrl, pkgrel), shell-escaping helpers (shEscape, bashArray), and dry-run-safe ship(); all previously flagged injection vectors are now guarded.
packages/targets/pkg-pacman/src/index.test.ts Comprehensive tests covering PKGBUILD generation, pkgver normalization, shell metacharacter escaping, bash -n syntax validation with hostile values, dry-run/live-throw, and all four assertValidNames rejection cases; test description updated from the previously misleading 'SKIP' wording.
packages/cli/src/adapter-registry.ts Adds pkg-pacman to the adapters list in alphabetical order; no other changes.
TARGETS.md Adds pkg-pacman row with status; correctly inserted in alphabetical position.
packages/targets/pkg-pacman/package.json Standard package manifest for the new adapter with workspace:* dependency on sh1pt-core; consistent with sibling packages.
packages/targets/pkg-pacman/tsconfig.json Extends root tsconfig.base.json; identical structure to other target adapters.
packages/targets/pkg-pacman/README.md Auto-generated README with usage and development instructions; no issues.
pnpm-lock.yaml Lockfile addition for the new pkg-pacman workspace package with a workspace:* link to core; expected and clean.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[build / ship called] --> B[assertValidNames]
    B -->|pkgname invalid| E1[throw invalid pkgname]
    B -->|repoName invalid| E2[throw invalid repoName]
    B -->|repoBaseUrl has newline or single-quote| E3[throw invalid repoBaseUrl]
    B -->|pkgrel not positive integer| E4[throw invalid pkgrel]
    B --> C{build or ship?}
    C -->|build| D[renderPkgbuild]
    D --> D1[pkgver normalization]
    D1 --> D2[shEscape pkgdesc / url / sourceUrl]
    D2 --> D3[bashArray for license / depends / sha256sum]
    D3 --> D4[writeFile PKGBUILD + .pacman.conf]
    D4 --> D5[return artifact + publishCommands in meta]
    C -->|ship dryRun=true| F[return dry-run id + publishCommands in meta]
    C -->|ship dryRun=false| G[throw not implemented]
Loading

Reviews (2): Last reviewed commit: "fix(pkg-pacman): validate repoBaseUrl + ..." | Re-trigger Greptile

Comment thread packages/targets/pkg-pacman/src/index.ts
Comment thread packages/targets/pkg-pacman/src/index.ts
Comment thread packages/targets/pkg-pacman/src/index.ts
Comment thread packages/targets/pkg-pacman/src/index.test.ts Outdated
- assertValidNames() now rejects repoBaseUrl containing newlines or single
  quotes (P1 security): a newline injected a fake [section] into the generated
  .pacman.conf; a single quote broke out of the rsync command quoting.
- Validate pkgrel is a positive integer (P2) — it's embedded unquoted in the
  PKGBUILD.
- Fix misleading test description (empty arrays, not SKIP); add rejection tests
  for hostile repoBaseUrl and pkgrel.
@Alexander-Sorrell-IT
Copy link
Copy Markdown
Author

Thanks — solid catch on repoBaseUrl. Addressed in the latest commit:

  • P1 (repoBaseUrl injection): assertValidNames() now rejects repoBaseUrl containing newlines or single-quote characters, closing both the .pacman.conf [section] newline-injection and the rsync single-quote breakout.
  • P2 (pkgrel): validated as a positive integer (it's embedded unquoted in the PKGBUILD).
  • Nit: renamed the misleading test (empty arrays, not SKIP); added rejection tests for hostile repoBaseUrl and pkgrel.

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