← Back to Docs

Contributing

The Linxira-OS/packages repository centrally manages the PKGBUILDs of every first-party Linxira OS package. CI builds each package in a clean Arch Linux container, signs it, and publishes it to the [linxira] repository on GitHub Pages. This page explains the repository layout, the four package source modes, and how to update or add a package.

Repository structure

packages/
├── packages/                  # each subdirectory = one package
│   ├── calamares/             # adopted upstream installer (release tarball + patch)
│   ├── linxira-catalog/       # first-party package (codeload commit mode)
│   ├── linxira-hwd-detector/ # first-party package
│   ├── shelly/                # adopted upstream package (codeload commit mode)
│   └── ...                    # 18 packages in total
├── scripts/
│   ├── check-boundaries.sh    # boundary check (CI first gate; update alongside PKGBUILD)
│   └── publish-repo.sh        # sign + repo-add + publish to GitHub Pages
├── .github/workflows/
│   └── packages.yml           # CI: boundaries → build (4) + system-stack (13) → publish
├── README.md                  # repo overview + per-package purpose
├── RELEASE.md                 # release process + key management
└── CONTRIBUTING.md            # this file

Package source modes

PKGBUILD source=() supports four forms, corresponding to four package source modes:

Mode A: codeload commit (most first-party packages)

The source is pinned to a commit; makepkg downloads it from codeload automatically and sha256 verifies integrity.

_commit=<40-hex SHA>
source=("$pkgname-$_commit.tar.gz::https://codeload.github.com/Linxira-OS/$pkgname/tar.gz/$_commit")
sha256sums=('<sha256 of the tarball>')

Mode B: release tarball (calamares)

Uses the upstream release tarball; tags are immutable.

source=("https://github.com/calamares/calamares/releases/download/v${pkgver}/calamares-${pkgver}.tar.gz")
sha256sums=('<upstream-published sha256>')

Mode C: git source (linxira-hooks)

Git source does not verify sha256 (git clone has its own integrity checks).

source=("git+$url.git#commit=$_commit")
sha256sums=('SKIP')

Mode D: local file (linxira-keyring)

The keyring's .gpg file lives directly in the same directory as the PKGBUILD.

source=("linxira.gpg")
sha256sums=('<sha256 of the local file>')

Updating a package (the most common operation)

When a first-party repository (e.g. linxira-catalog) gets a new commit, update the PKGBUILD in the packages repository:

Step 1: get the full SHA of the new commit

# in the source repository
git log --oneline -1
# output: 9dd16cda... (use the full 40-character SHA)

Step 2: update the PKGBUILD

Change two things: _commit=<new 40-hex SHA> and sha256sums=('<new tarball sha256>'). Three ways to compute the new sha256 (Arch environment):

# Method 1: updpkgsums (recommended; updates the PKGBUILD automatically)
cd packages/linxira-catalog
updpkgsums

# Method 2: makepkg -g (prints only the new sha256; paste it manually)
cd packages/linxira-catalog
makepkg -g

# Method 3: download and hash manually
curl -L "https://codeload.github.com/Linxira-OS/linxira-catalog/tar.gz/<commit>" -o /tmp/tarball.tar.gz
sha256sum /tmp/tarball.tar.gz

If pkgver or pkgrel also need updating, change them at the same time.

Step 3: sync check-boundaries.sh

This step is the easiest to forget.

scripts/check-boundaries.sh hardcodes each package's _commit and sha256sums. After changing the PKGBUILD you must update the matching lines in this script, otherwise the CI boundaries job fails.

# Find your package's lines in check-boundaries.sh
grep linxira-catalog scripts/check-boundaries.sh
# Output: two lines:
#   grep -q '89b25593...' packages/linxira-catalog/PKGBUILD
#   grep -q 'bdf3657d...' packages/linxira-catalog/PKGBUILD
# Update both hashes to the new values in the PKGBUILD

Step 4: verify locally

# Run the boundary check (same as CI)
bash scripts/check-boundaries.sh

# If you have an Arch environment, try building
cd packages/linxira-catalog
makepkg -f

Step 5: commit

git add packages/<pkg>/PKGBUILD scripts/check-boundaries.sh
git commit -m "update <pkg> to <first 7 chars of commit>"
git push

After the push, CI runs automatically: boundaries → build/system-stack. If CI is green, the package is built automatically (artifacts are downloadable).

CI pipeline

push/PR
  │
  ├─ boundaries          # check-boundaries.sh (seconds)
  │
  ├─ build (matrix)      # calamares / artwork / hooks / shelly
  │   └─ docker archlinux:base-devel → makepkg
  │
  ├─ system-stack        # 13 linxira-* packages, built in dependency order
  │   └─ docker archlinux:base-devel → makepkg + pacman -U (installed into the container for downstream packages)
  │
  └─ publish (manual only)  # sign + repo-add → GitHub Pages

Common causes of CI failures

CauseSymptomFix
sha256 mismatch==> ERROR: One or more files did not pass the validity check!Recompute the sha256: makepkg -g
_commit updated but sha256 notSame as aboveUpdate _commit and sha256 together
check-boundaries.sh not syncedboundaries job failsSync the hardcoded _commit/sha256
Missing makedependserror: header file not found or bindgen failedAdd the missing package to makedepends in the PKGBUILD
CRLF issuemakepkg reports strange errors while parsing the PKGBUILDMake sure the PKGBUILD uses LF line endings (.gitattributes or dos2unix)

Adding a new package

  1. Create a subdirectory under packages/ and put the PKGBUILD in it
  2. If there are patches or extra files, put them in the same directory
  3. If the package must be part of system-stack, add its name to the packages=(...) array in packages.yml
  4. If boundary checks are needed, add a check rule in check-boundaries.sh
  5. Make sure the package has groups=('linxira') so pacman -S linxira can discover it

Keys and signing

See RELEASE.md for details. Key points:

Things not to do