Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions .github/workflows/publish-apt-repository.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Publish APT repository

on:
push:
branches: [main]
paths:
- apt-repository/**
- .github/workflows/publish-apt-repository.yml
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: false

jobs:
build:
name: Build signed APT repository
runs-on: ubuntu-26.04
env:
APT_REPOSITORY_SIGNING_KEY: ${{ secrets.APT_REPOSITORY_SIGNING_KEY }}
APT_REPOSITORY_SIGNING_PASSPHRASE: ${{ secrets.APT_REPOSITORY_SIGNING_PASSPHRASE }}
EXPECTED_SIGNING_FINGERPRINT: ${{ secrets.APT_REPOSITORY_SIGNING_FINGERPRINT }}
GNUPGHOME: ${{ runner.temp }}/gnupg

steps:
- name: Checkout
uses: actions/checkout@v7
with:
persist-credentials: false

- name: Configure GitHub Pages
uses: actions/configure-pages@v6

- name: Install repository build tools
run: |
sudo apt-get update
sudo apt-get install --yes apt-utils gnupg

- name: Import and verify repository signing key
run: |
if [[ -z "$EXPECTED_SIGNING_FINGERPRINT" ]]; then
echo "APT_REPOSITORY_SIGNING_FINGERPRINT Actions secret is required." >&2
exit 1
fi
mkdir --mode=0700 "$GNUPGHOME"
printf '%s' "$APT_REPOSITORY_SIGNING_KEY" | gpg --batch --import
signing_fingerprint="$(gpg --batch --with-colons --list-secret-keys \
| awk -F: '$1 == "fpr" { print $10; exit }')"
if [[ "$signing_fingerprint" != "$EXPECTED_SIGNING_FINGERPRINT" ]]; then
echo "The imported signing key does not match APT_REPOSITORY_SIGNING_FINGERPRINT." >&2
exit 1
fi
printf '%s\n' "$signing_fingerprint" > "$RUNNER_TEMP/signing-fingerprint"

- name: Generate and sign repository metadata
run: |
site_dir="$RUNNER_TEMP/site"
distribution_dir="$site_dir/dists/stable"
signing_fingerprint="$(<"$RUNNER_TEMP/signing-fingerprint")"
mkdir --parents "$site_dir"
cp --archive apt-repository/. "$site_dir/"
find "$site_dir" -type f -name .gitkeep -delete
mkdir --parents "$distribution_dir/main/binary-all" "$distribution_dir/main/source"

(
cd "$site_dir"
apt-ftparchive packages pool/main > dists/stable/main/binary-all/Packages
gzip --keep --force dists/stable/main/binary-all/Packages
apt-ftparchive sources pool/main > dists/stable/main/source/Sources
gzip --keep --force dists/stable/main/source/Sources

apt-ftparchive \
-o APT::FTPArchive::Release::Origin="itsallcode" \
-o APT::FTPArchive::Release::Label="OpenFastTrace" \
-o APT::FTPArchive::Release::Suite="stable" \
-o APT::FTPArchive::Release::Codename="stable" \
-o APT::FTPArchive::Release::Architectures="all" \
-o APT::FTPArchive::Release::Components="main" \
-o APT::FTPArchive::Release::Description="OpenFastTrace Debian packages" \
release dists/stable > dists/stable/Release
)

gpg --batch --yes --local-user "$signing_fingerprint" \
--pinentry-mode loopback --passphrase "$APT_REPOSITORY_SIGNING_PASSPHRASE" \
--armor --detach-sign --output "$distribution_dir/Release.gpg" "$distribution_dir/Release"
gpg --batch --yes --local-user "$signing_fingerprint" \
--pinentry-mode loopback --passphrase "$APT_REPOSITORY_SIGNING_PASSPHRASE" \
--clearsign --output "$distribution_dir/InRelease" "$distribution_dir/Release"
gpg --batch --armor --export "$signing_fingerprint" \
> "$site_dir/itsallcode-archive-keyring.asc"
printf '%s\n' "$signing_fingerprint" \
> "$site_dir/itsallcode-archive-keyring.fingerprint"

- name: Upload GitHub Pages artifact
uses: actions/upload-pages-artifact@v5
with:
path: ${{ runner.temp }}/site

deploy:
name: Deploy APT repository
needs: build
runs-on: ubuntu-26.04
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
113 changes: 60 additions & 53 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
VERSION: ${{ inputs.version }}
PACKAGE_REVISION: ${{ inputs.package_revision }}
PACKAGE_VERSION: ${{ inputs.version }}-${{ inputs.package_revision }}
PACKAGE_POOL_DIR: apt-repository/pool/main/o/openfasttrace

steps:
- name: Checkout
Expand All @@ -44,69 +45,75 @@ jobs:
script: |
core.setFailed('Not running on main branch. Start this workflow from main.')

- name: Install Debian build dependencies
- name: Validate committed package artifacts
run: |
sudo apt-get update
sudo apt-get install --yes \
appstream \
build-essential \
curl \
debhelper \
devscripts \
dpkg-dev \
imagemagick \
maven \
openjdk-17-jdk-headless \
pandoc \
shellcheck \
wget
readonly orig_tarball="openfasttrace_${VERSION}.orig.tar.gz"
readonly debian_tarball="openfasttrace_${PACKAGE_VERSION}.debian.tar.xz"
readonly dsc_file="openfasttrace_${PACKAGE_VERSION}.dsc"
readonly binary_package="openfasttrace_${PACKAGE_VERSION}_all.deb"
readonly checksum_file="openfasttrace_${PACKAGE_VERSION}.SHA256SUMS"
readonly artifacts=(
"$orig_tarball"
"$debian_tarball"
"$dsc_file"
"$binary_package"
"$checksum_file"
)

- name: Configure Maven toolchain
run: |
jdk_home="$(dirname "$(dirname "$(readlink -f "$(command -v javac)")")")"
mkdir --parents "$HOME/.m2"
cat > "$HOME/.m2/toolchains.xml" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<toolchains>
<toolchain>
<type>jdk</type>
<provides>
<version>17</version>
</provides>
<configuration>
<jdkHome>$jdk_home</jdkHome>
</configuration>
</toolchain>
</toolchains>
EOF

- name: Create source package
run: ./create-source-package.sh "$VERSION" "$PACKAGE_REVISION"
if [[ ! -d "$PACKAGE_POOL_DIR" ]]; then
echo "Error: The APT package pool is missing: $PACKAGE_POOL_DIR" >&2
echo "Mitigation: merge the package pull request that adds version $PACKAGE_VERSION before releasing it." >&2
exit 1
fi

- name: Create binary package
run: ./create-binary-package.sh "$VERSION" "$PACKAGE_REVISION"

- name: Generate SHA-256 checksums
run: |
missing_artifacts=0
for artifact in "${artifacts[@]}"; do
if [[ ! -f "$PACKAGE_POOL_DIR/$artifact" ]]; then
echo "Error: Missing committed package artifact: $PACKAGE_POOL_DIR/$artifact" >&2
missing_artifacts=1
fi
done
if [[ "$missing_artifacts" -ne 0 ]]; then
echo "Mitigation: create and stage the package, then commit and merge the staged files:" >&2
echo " ./create-source-package.sh $VERSION $PACKAGE_REVISION" >&2
echo " ./create-binary-package.sh $VERSION $PACKAGE_REVISION" >&2
echo " ./stage-apt-package.sh $VERSION $PACKAGE_REVISION" >&2
exit 1
fi
(
cd out
sha256sum \
"openfasttrace_${VERSION}.orig.tar.gz" \
"openfasttrace_${PACKAGE_VERSION}.debian.tar.xz" \
"openfasttrace_${PACKAGE_VERSION}.dsc" \
"openfasttrace_${PACKAGE_VERSION}_all.deb"
) > out/SHA256SUMS
cd "$PACKAGE_POOL_DIR"
if ! sha256sum --check "$checksum_file"; then
echo "Error: The checksum manifest for $PACKAGE_VERSION does not match the committed package artifacts." >&2
echo "Mitigation: regenerate the staged package with ./stage-apt-package.sh $VERSION $PACKAGE_REVISION and commit the updated files." >&2
exit 1
fi
)
if [[ "$(dpkg-deb --field "$PACKAGE_POOL_DIR/$binary_package" Package)" != "openfasttrace" ]]; then
echo "Error: $binary_package is not an openfasttrace package." >&2
echo "Mitigation: stage the package produced by ./create-binary-package.sh $VERSION $PACKAGE_REVISION." >&2
exit 1
fi
if [[ "$(dpkg-deb --field "$PACKAGE_POOL_DIR/$binary_package" Version)" != "$PACKAGE_VERSION" ]]; then
echo "Error: $binary_package does not declare Debian version $PACKAGE_VERSION." >&2
echo "Mitigation: stage matching source and binary artifacts for version $PACKAGE_VERSION." >&2
exit 1
fi
if [[ "$(dpkg-deb --field "$PACKAGE_POOL_DIR/$binary_package" Architecture)" != "all" ]]; then
echo "Error: $binary_package is not architecture-independent." >&2
echo "Mitigation: stage the OpenFastTrace all-architecture package for version $PACKAGE_VERSION." >&2
exit 1
fi

- name: Create GitHub release
run: |
gh release create "$PACKAGE_VERSION" \
--target main \
--title "$PACKAGE_VERSION: OpenFastTrace Debian Package" \
--generate-notes \
"out/openfasttrace_${VERSION}.orig.tar.gz" \
"out/openfasttrace_${PACKAGE_VERSION}.debian.tar.xz" \
"out/openfasttrace_${PACKAGE_VERSION}.dsc" \
"out/openfasttrace_${PACKAGE_VERSION}_all.deb" \
out/SHA256SUMS
"$PACKAGE_POOL_DIR/openfasttrace_${VERSION}.orig.tar.gz" \
"$PACKAGE_POOL_DIR/openfasttrace_${PACKAGE_VERSION}.debian.tar.xz" \
"$PACKAGE_POOL_DIR/openfasttrace_${PACKAGE_VERSION}.dsc" \
"$PACKAGE_POOL_DIR/openfasttrace_${PACKAGE_VERSION}_all.deb" \
"$PACKAGE_POOL_DIR/openfasttrace_${PACKAGE_VERSION}.SHA256SUMS"
env:
GH_TOKEN: ${{ github.token }}
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ We also will not accept contributions that are clearly generated by AI agents bu

## Testing

We are happy if you test the package, especially on Debian-derived platforms that are not covered by our automation. If you find a packaging bug, please open an [issue](https://github.com/itsallcode/openfasttrace-debian-package/issues/new). Include enough information to reproduce it, such as the distribution, version, architecture, package version, command, and output.
We are happy if you test the package, especially on Debian-derived platforms that are not covered by our automation. If you find a packaging bug, please open an [issue](https://github.com/itsallcode/itsallcode-apt-repository/issues/new). Include enough information to reproduce it, such as the distribution, version, architecture, package version, command, and output.

Before submitting a packaging change, run the relevant checks. The full integration test builds the source and binary packages, checks their contents, runs ShellCheck, and validates AppStream metadata:

Expand All @@ -36,7 +36,7 @@ Before submitting a packaging change, run the relevant checks. The full integrat

## Ideas

If you have an idea to improve packaging or distribution, open a [feature request](https://github.com/itsallcode/openfasttrace-debian-package/issues/new).
If you have an idea to improve packaging or distribution, open a [feature request](https://github.com/itsallcode/itsallcode-apt-repository/issues/new).

# Style Guides

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

This repository builds Debian packages for [OpenFastTrace](https://github.com/itsallcode/openfasttrace) (OFT), a requirement tracing suite. OFT keeps track of whether you implemented everything planned in your specifications and identifies obsolete parts of a product.

[![Build Debian package](https://github.com/itsallcode/openfasttrace-debian-package/actions/workflows/build.yml/badge.svg)](https://github.com/itsallcode/openfasttrace-debian-package/actions/workflows/build.yml)
[![Build Debian package](https://github.com/itsallcode/itsallcode-apt-repository/actions/workflows/build.yml/badge.svg)](https://github.com/itsallcode/itsallcode-apt-repository/actions/workflows/build.yml)

## Getting the Package

Pre-built source and binary packages are available from the [GitHub releases](https://github.com/itsallcode/openfasttrace-debian-package/releases). Install the binary package with its Java runtime dependency:
Pre-built source and binary packages are available from the [GitHub releases](https://github.com/itsallcode/itsallcode-apt-repository/releases). Install the binary package with its Java runtime dependency:

```sh
sudo apt install ./openfasttrace_<version>-<package-revision>_all.deb
Expand All @@ -28,9 +28,10 @@ On Debian or a derived distribution, install the tools listed by the preconditio
./check-preconditions.sh
./create-source-package.sh <version> [package-revision]
./create-binary-package.sh <version> [package-revision]
./stage-apt-package.sh <version> [package-revision]
```

The resulting artifacts are placed in `out/`. The scripts download the specified OpenFastTrace source release, incorporate this repository's `debian/` packaging metadata, and build the package.
The build artifacts are placed in `out/`. The scripts download the specified OpenFastTrace source release, incorporate this repository's `debian/` packaging metadata, and build the package. `stage-apt-package.sh` validates the resulting source and binary packages, then copies them into the Debian archive pool under `apt-repository/` for inclusion in a package pull request.

## Project Information

Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ We provide security updates for the latest package release. Security fixes to Op

## Reporting a Vulnerability

If you discover a potential security issue in this packaging repository or its published packages, please report it privately via [GitHub Security Advisories](https://github.com/itsallcode/openfasttrace-debian-package/security/advisories/new). For a vulnerability in OpenFastTrace itself, use the [upstream security reporting channel](https://github.com/itsallcode/openfasttrace/security/advisories/new).
If you discover a potential security issue in this packaging repository or its published packages, please report it privately via [GitHub Security Advisories](https://github.com/itsallcode/itsallcode-apt-repository/security/advisories/new). For a vulnerability in OpenFastTrace itself, use the [upstream security reporting channel](https://github.com/itsallcode/openfasttrace/security/advisories/new).

We follow coordinated disclosure and aim to:

Expand Down
28 changes: 28 additions & 0 deletions apt-repository/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# OpenFastTrace APT Repository

This directory is the document root published at `https://apt.itsallcode.org/openfasttrace`. The visitor-facing installation page is [index.html](index.html).

## Installation

Install the repository's public key in a dedicated keyring and add the signed repository source:

```sh
sudo install --directory --mode=0755 /etc/apt/keyrings
curl --fail --silent --show-error --location \
https://apt.itsallcode.org/openfasttrace/itsallcode-archive-keyring.asc \
| sudo gpg --dearmor --yes --output /etc/apt/keyrings/itsallcode-archive-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/itsallcode-archive-keyring.gpg] https://apt.itsallcode.org/openfasttrace stable main' \
| sudo tee /etc/apt/sources.list.d/openfasttrace.list > /dev/null
sudo apt update
sudo apt install openfasttrace
```

The public key fingerprint is published at `https://apt.itsallcode.org/openfasttrace/itsallcode-archive-keyring.fingerprint`. Check it before trusting a newly downloaded key.

It follows the Debian archive layout:

* `pool/main/o/openfasttrace/` contains the OpenFastTrace binary and source package artifacts. A package pull request adds its `.deb`, `.dsc`, original
source tarball, and Debian tarball here.
* `dists/stable/main/binary-all/` contains the generated binary package index for the architecture-independent OpenFastTrace package.
* `dists/stable/main/source/` contains the generated source package index.
* `dists/stable/` contains the generated and signed `Release`,`InRelease`, and `Release.gpg` files.
1 change: 1 addition & 0 deletions apt-repository/dists/stable/main/binary-all/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions apt-repository/dists/stable/main/source/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

42 changes: 42 additions & 0 deletions apt-repository/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>itsallcode.org APT Repository</title>
</head>
<body>
<h1>itsallcode.org APT Repository</h1>
<p>
This repository provides itsallcode.org's Debian packages for the <code>stable</code> suite and <code>main</code> component. OpenFastTrace is the most prominent example.
</p>

<h2>Installing Packages From This Repository</h2>
<ol>
<li>
<p>Install the archive key in a dedicated APT keyring.</p>
<pre>sudo install --directory --mode=0755 /etc/apt/keyrings
curl --fail --silent --show-error --location \
https://apt.itsallcode.org/openfasttrace/itsallcode-archive-keyring.asc \
| sudo gpg --dearmor --yes --output /etc/apt/keyrings/itsallcode-archive-keyring.gpg</pre>
</li>
<li>
<p>Add the signed repository source.</p>
<pre>echo 'deb [signed-by=/etc/apt/keyrings/itsallcode-archive-keyring.gpg] https://apt.itsallcode.org/openfasttrace stable main' \
| sudo tee /etc/apt/sources.list.d/openfasttrace.list &gt; /dev/null</pre>
</li>
<li>
<p>Update APT and install the package.</p>
<pre>sudo apt update</pre>
</li>
<li>
<p>Install a package, for example <code>openfasttrace</code>.</p>
<pre>sudo apt install openfasttrace</pre>
</li>
</ol>

<p>
Before trusting the key, verify its <a href="itsallcode-archive-keyring.fingerprint">published fingerprint</a>. The <a href="itsallcode-archive-keyring.asc">ASCII-armored public key</a> is also available directly.
</p>
</body>
</html>
Loading