From 21c8ff75cd51edb41e867a32ae1330e84ec6c159 Mon Sep 17 00:00:00 2001 From: Simon Beaudoin Date: Wed, 10 Jun 2026 19:22:12 -0700 Subject: [PATCH 1/4] ci: support suite-aware extra repos Add debian/extra-repositories.txt parsing for build_package. Support suite filters like [noble,questing] and suite placeholders. Pass selected entries to all sbuild invocation paths. Signed-off-by: Simon Beaudoin --- .github/actions/build_package/action.yml | 110 +++++++++++++++++++++-- docs/actions/build_package.md | 60 ++++++++++--- 2 files changed, 147 insertions(+), 23 deletions(-) diff --git a/.github/actions/build_package/action.yml b/.github/actions/build_package/action.yml index 944b1beb..31c1928a 100644 --- a/.github/actions/build_package/action.yml +++ b/.github/actions/build_package/action.yml @@ -160,6 +160,87 @@ runs: # subsequent cd operations might change the working directory. BUILD_DIR_ABS=$(realpath "../${{inputs.build-dir}}") + # Optional repo-local extension point for additional build-dependency apt repos. + # Each non-empty, non-comment line in debian/extra-repositories.txt is passed + # through to sbuild as --extra-repository "". + # + # Supported entry formats: + # deb [arch=arm64 ...] https://example.org/repo {suite} main + # -> applies to all suites + # + # [noble,questing] deb [arch=arm64 ...] https://ppa.launchpadcontent.net/org/ppa/ubuntu noble main + # -> applies only when target suite is listed + # + # Placeholders replaced with the runtime suite: + # {suite}, {SUITE}, ${suite}, ${SUITE}, @suite@, @SUITE@ + EXTRA_REPOSITORIES_FILE="./debian/extra-repositories.txt" + target_suite="${{inputs.suite}}" + if [[ "$target_suite" == "unstable" ]]; then + target_suite="sid" + fi + extra_repository_values=() + extra_repository_args=() + declare -A extra_repository_seen=() + + if [[ -f "$EXTRA_REPOSITORIES_FILE" ]]; then + echo "ℹ️ Found ${EXTRA_REPOSITORIES_FILE}; loading extra sbuild repositories" + + while IFS= read -r raw_line || [[ -n "$raw_line" ]]; do + line="$(printf '%s' "$raw_line" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')" + [[ -n "$line" ]] || continue + [[ "$line" =~ ^# ]] && continue + + repo_entry="$line" + + if [[ "$line" =~ ^\[([^][]+)\][[:space:]]+(.+)$ ]]; then + suites_csv="${BASH_REMATCH[1]}" + repo_entry="${BASH_REMATCH[2]}" + include_entry=false + + IFS=',' read -ra suite_filters <<< "$suites_csv" + for suite_filter in "${suite_filters[@]}"; do + suite_filter="$(printf '%s' "$suite_filter" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')" + [[ -n "$suite_filter" ]] || continue + if [[ "$suite_filter" == "$target_suite" || "$suite_filter" == "all" || "$suite_filter" == "*" ]]; then + include_entry=true + break + fi + done + + if [[ "$include_entry" != true ]]; then + echo "ℹ️ Skipping entry with suite filter [${suites_csv}] for target suite ${target_suite}" + continue + fi + fi + + repo_entry="${repo_entry//\$\{suite\}/$target_suite}" + repo_entry="${repo_entry//\$\{SUITE\}/$target_suite}" + repo_entry="${repo_entry//\{suite\}/$target_suite}" + repo_entry="${repo_entry//\{SUITE\}/$target_suite}" + repo_entry="${repo_entry//@suite@/$target_suite}" + repo_entry="${repo_entry//@SUITE@/$target_suite}" + repo_entry="$(printf '%s' "$repo_entry" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')" + [[ -n "$repo_entry" ]] || continue + + if [[ -n "${extra_repository_seen[$repo_entry]+x}" ]]; then + continue + fi + extra_repository_seen["$repo_entry"]=1 + + extra_repository_values+=("$repo_entry") + extra_repository_args+=(--extra-repository "$repo_entry") + done < "$EXTRA_REPOSITORIES_FILE" + + if (( ${#extra_repository_values[@]} > 0 )); then + echo "ℹ️ Loaded ${#extra_repository_values[@]} extra repository entries:" + printf ' - %s\n' "${extra_repository_values[@]}" + else + echo "ℹ️ ${EXTRA_REPOSITORIES_FILE} has no active entries (only blank/comment lines)" + fi + else + echo "ℹ️ No ${EXTRA_REPOSITORIES_FILE} found; using default repositories only" + fi + set +e if [[ "$PREBUILT_MODE" == "true" ]]; then @@ -201,6 +282,7 @@ runs: $lintian_flag \ --build-dir "$BUILD_DIR_ABS" \ --build-dep-resolver=apt \ + "${extra_repository_args[@]}" \ "$DSC_FILE" else # ℹ️ Prebuilt mode + native source format: invoke sbuild directly — @@ -212,7 +294,8 @@ runs: --dist=${{inputs.suite}} \ $lintian_flag \ --build-dir "$BUILD_DIR_ABS" \ - --build-dep-resolver=apt + --build-dep-resolver=apt \ + "${extra_repository_args[@]}" fi else @@ -220,17 +303,26 @@ runs: # --git-ignore-branch is necessary because the debian branch actually checked out can be any (ex, debian/1.0.0) because we can build any previous tag # ℹ️ chroot mode unshare is important to bypass privilege issues with the mounting # Host Architecture: The architecture for which the binaries are being built (invariably arm64). + sbuild_builder_cmd=( + sbuild + --no-clean-source + --dpkg-source-opt=--extend-diff-ignore=^\\.github + --host=arm64 + --build=${{env.BUILD_ARCH}} + --dist=${{inputs.suite}} + "$lintian_flag" + --build-dir + "$BUILD_DIR_ABS" + --build-dep-resolver=apt + "${extra_repository_args[@]}" + ) + printf -v sbuild_builder_escaped '%q ' "${sbuild_builder_cmd[@]}" + sbuild_builder_escaped="${sbuild_builder_escaped% }" + gbp buildpackage \ --git-no-pristine-tar \ --git-ignore-branch \ - --git-builder="sbuild --no-clean-source \ - --dpkg-source-opt="--extend-diff-ignore=^\\.github" \ - --host=arm64 \ - --build=${{env.BUILD_ARCH}} \ - --dist=${{inputs.suite}} \ - $lintian_flag \ - --build-dir $BUILD_DIR_ABS \ - --build-dep-resolver=apt" + --git-builder="$sbuild_builder_escaped" fi RET=$? diff --git a/docs/actions/build_package.md b/docs/actions/build_package.md index 86bef7c7..b85238c2 100644 --- a/docs/actions/build_package.md +++ b/docs/actions/build_package.md @@ -13,6 +13,39 @@ | `build-dir` | Yes | - | Directory where build artifacts will be placed | | `run-lintian` | No | `false` | Whether to run lintian quality checks | +## Optional Repo File + +If the package repository contains `debian/extra-repositories.txt`, each +active entry is forwarded to `sbuild` as: + +```bash +--extra-repository "" +``` + +This applies to all build modes (source/gbp and prebuilt/native/quilt). + +Supported entry forms: + +```text +# Applies to all suites: +deb [arch=arm64 signed-by=/etc/apt/keyrings/vendor.gpg] https://repo.example.org/debian {suite} main + +# Applies only to specific suites: +[noble,questing,resolute] deb [arch=arm64 trusted=yes] https://ppa.launchpadcontent.net/example/team/ubuntu noble main +``` + +Notes: +- Lines beginning with `#` and empty lines are ignored. +- Suite filters support `all` or `*` as wildcards. +- Suite placeholders are expanded at runtime: `{suite}`, `{SUITE}`, `${suite}`, `${SUITE}`, `@suite@`, `@SUITE@`. + +Example: + +```text +# Extra dependency repositories for this package +deb [arch=arm64 signed-by=/etc/apt/keyrings/vendor.gpg] https://ppa.launchpadcontent.net/example/team/ubuntu noble main +``` + ## Process Flow ```mermaid @@ -23,11 +56,11 @@ flowchart TD D -->|quilt| E[Quilt Format OK] D -->|native| F[Native Format OK] D -->|unknown| G[Error: Unsupported] - E --> H{Check for Extra Repo} + E --> H{debian/extra-repositories.txt exists?} F --> H - H -->|Available| I[Add pkg.qualcomm.com repo] - H -->|Not Available| J[Skip Extra Repo] - I --> K[Run gbp buildpackage] + H -->|Yes| I[Pass each entry as --extra-repository] + H -->|No| J[Use default apt repositories only] + I --> K[Run sbuild/gbp buildpackage] J --> K K --> L{Lintian Enabled?} L -->|Yes| M[Run with --run-lintian] @@ -53,15 +86,14 @@ The action determines the build configuration based on the runner architecture: The action runs git-buildpackage with sbuild: ```bash -gbp buildpackage \ - --git-ignore-branch \ - --git-builder="sbuild --host=arm64 \ - --build=${BUILD_ARCH} \ - --dist=${suite} \ - ${lintian_flag} \ - --build-dir ../${build-dir} \ - --build-dep-resolver=apt \ - ${EXTRA_REPO}" +sbuild --no-clean-source \ + --host=arm64 \ + --build=${BUILD_ARCH} \ + --dist=${suite} \ + ${lintian_flag} \ + --build-dir ../${build-dir} \ + --build-dep-resolver=apt \ + [--extra-repository "" ...] ``` ## Key Features @@ -69,7 +101,7 @@ gbp buildpackage \ - **Cross-compilation support**: Can build ARM64 packages on x86_64 hosts - **Native builds**: Can build ARM64 packages on ARM64 hosts (faster) - **Chroot isolation**: Uses sbuild with unshare mode for clean builds -- **Extra repository**: Automatically adds internal Qualcomm repo if available +- **Extra repositories**: Loads repo-specific entries from `debian/extra-repositories.txt` and passes them via `--extra-repository` - **Error handling**: Prints build log tail on failure for debugging - **Source format detection**: Supports both quilt and native formats From 9c49b81e046b0e1256d5e394da59c8303074c729 Mon Sep 17 00:00:00 2001 From: Simon Beaudoin Date: Thu, 11 Jun 2026 10:27:15 -0700 Subject: [PATCH 2/4] docs: note extra repo file contract Document debian/extra-repositories.txt in AGENTS.md. Describe suite filters, wildcard support, and placeholders. Signed-off-by: Simon Beaudoin --- AGENTS.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index a8622974..3901435f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -29,6 +29,18 @@ orchestration around build, test, promotion, and release flows. published from `qualcomm-linux/debusine-action`, while the Ubuntu-capable `pkg-builder` images are still consumed from GHCR by the local path. +## Package Repo Extra Repositories + +- The `build_package` composite action supports an optional + `debian/extra-repositories.txt` file in package repositories. +- Active entries are passed to `sbuild` as `--extra-repository`. +- Supported entry styles: + - global entries (apply to all suites) + - suite-filtered entries (for example `[noble,questing] deb ...`) + - wildcards (`[all]` or `[*]`) +- Suite placeholders are expanded at runtime: + - `{suite}`, `{SUITE}`, `${suite}`, `${SUITE}`, `@suite@`, `@SUITE@` + ## Workflow Naming Convention - `pkg-*` workflow names are for package lifecycle flows (`build`, `promote`, `release`, and From 068c6e58e8d6ce8b48a2d7c65b4f46ede18f852d Mon Sep 17 00:00:00 2001 From: Simon Beaudoin Date: Mon, 15 Jun 2026 11:26:45 -0700 Subject: [PATCH 3/4] build_package: simplify extra-repositories parsing Keep only global entries and explicit suite-filtered entries in debian/extra-repositories.txt. Remove wildcard and placeholder handling. Keep sid/unstable alias matching for suite filters. Update docs to reflect the simplified contract. Signed-off-by: Simon Beaudoin --- .github/actions/build_package/action.yml | 55 ++++++++++++------------ AGENTS.md | 5 +-- docs/actions/build_package.md | 6 +-- 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/.github/actions/build_package/action.yml b/.github/actions/build_package/action.yml index 31c1928a..4970ff77 100644 --- a/.github/actions/build_package/action.yml +++ b/.github/actions/build_package/action.yml @@ -162,17 +162,14 @@ runs: # Optional repo-local extension point for additional build-dependency apt repos. # Each non-empty, non-comment line in debian/extra-repositories.txt is passed - # through to sbuild as --extra-repository "". + # to sbuild as --extra-repository "". # # Supported entry formats: - # deb [arch=arm64 ...] https://example.org/repo {suite} main + # deb [arch=arm64 ...] https://example.org/repo noble main # -> applies to all suites # # [noble,questing] deb [arch=arm64 ...] https://ppa.launchpadcontent.net/org/ppa/ubuntu noble main # -> applies only when target suite is listed - # - # Placeholders replaced with the runtime suite: - # {suite}, {SUITE}, ${suite}, ${SUITE}, @suite@, @SUITE@ EXTRA_REPOSITORIES_FILE="./debian/extra-repositories.txt" target_suite="${{inputs.suite}}" if [[ "$target_suite" == "unstable" ]]; then @@ -192,33 +189,35 @@ runs: repo_entry="$line" - if [[ "$line" =~ ^\[([^][]+)\][[:space:]]+(.+)$ ]]; then - suites_csv="${BASH_REMATCH[1]}" - repo_entry="${BASH_REMATCH[2]}" - include_entry=false - - IFS=',' read -ra suite_filters <<< "$suites_csv" - for suite_filter in "${suite_filters[@]}"; do - suite_filter="$(printf '%s' "$suite_filter" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')" - [[ -n "$suite_filter" ]] || continue - if [[ "$suite_filter" == "$target_suite" || "$suite_filter" == "all" || "$suite_filter" == "*" ]]; then - include_entry=true - break + if [[ "$line" == \[* ]]; then + if [[ "$line" =~ ^\[([^][]+)\][[:space:]]+(.+)$ ]]; then + suites_csv="${BASH_REMATCH[1]}" + repo_entry="${BASH_REMATCH[2]}" + include_entry=false + + IFS=',' read -ra suite_filters <<< "$suites_csv" + for suite_filter in "${suite_filters[@]}"; do + suite_filter="$(printf '%s' "$suite_filter" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')" + [[ -n "$suite_filter" ]] || continue + if [[ "$suite_filter" == "unstable" ]]; then + suite_filter="sid" + fi + if [[ "$suite_filter" == "$target_suite" ]]; then + include_entry=true + break + fi + done + + if [[ "$include_entry" != true ]]; then + echo "ℹ️ Skipping entry with suite filter [${suites_csv}] for target suite ${target_suite}" + continue fi - done - - if [[ "$include_entry" != true ]]; then - echo "ℹ️ Skipping entry with suite filter [${suites_csv}] for target suite ${target_suite}" - continue + else + echo "::error::Invalid ${EXTRA_REPOSITORIES_FILE} entry '${line}'. Expected '[suite1,suite2] deb ...' or a plain 'deb ...' line." + exit 1 fi fi - repo_entry="${repo_entry//\$\{suite\}/$target_suite}" - repo_entry="${repo_entry//\$\{SUITE\}/$target_suite}" - repo_entry="${repo_entry//\{suite\}/$target_suite}" - repo_entry="${repo_entry//\{SUITE\}/$target_suite}" - repo_entry="${repo_entry//@suite@/$target_suite}" - repo_entry="${repo_entry//@SUITE@/$target_suite}" repo_entry="$(printf '%s' "$repo_entry" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')" [[ -n "$repo_entry" ]] || continue diff --git a/AGENTS.md b/AGENTS.md index 3901435f..fa832575 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,9 +37,8 @@ orchestration around build, test, promotion, and release flows. - Supported entry styles: - global entries (apply to all suites) - suite-filtered entries (for example `[noble,questing] deb ...`) - - wildcards (`[all]` or `[*]`) -- Suite placeholders are expanded at runtime: - - `{suite}`, `{SUITE}`, `${suite}`, `${SUITE}`, `@suite@`, `@SUITE@` +- Suite filters are exact matches against the build suite. +- `unstable` and `sid` are treated as equivalent for suite-filter matching. ## Workflow Naming Convention diff --git a/docs/actions/build_package.md b/docs/actions/build_package.md index b85238c2..29b87187 100644 --- a/docs/actions/build_package.md +++ b/docs/actions/build_package.md @@ -28,7 +28,7 @@ Supported entry forms: ```text # Applies to all suites: -deb [arch=arm64 signed-by=/etc/apt/keyrings/vendor.gpg] https://repo.example.org/debian {suite} main +deb [arch=arm64 signed-by=/etc/apt/keyrings/vendor.gpg] https://repo.example.org/debian noble main # Applies only to specific suites: [noble,questing,resolute] deb [arch=arm64 trusted=yes] https://ppa.launchpadcontent.net/example/team/ubuntu noble main @@ -36,8 +36,8 @@ deb [arch=arm64 signed-by=/etc/apt/keyrings/vendor.gpg] https://repo.example.org Notes: - Lines beginning with `#` and empty lines are ignored. -- Suite filters support `all` or `*` as wildcards. -- Suite placeholders are expanded at runtime: `{suite}`, `{SUITE}`, `${suite}`, `${SUITE}`, `@suite@`, `@SUITE@`. +- Suite filters are exact matches against the build suite. +- `unstable` and `sid` are treated as equivalent for suite-filter matching. Example: From 4723748fe0080172798b0f78add90b031d6e2b21 Mon Sep 17 00:00:00 2001 From: Simon Beaudoin Date: Wed, 17 Jun 2026 11:52:32 -0700 Subject: [PATCH 4/4] ci: test debusine extra repositories branch Point DEBUSINE_ACTION_REF to dev/sbeaudoi-extra-repositories. This enables pkg-example trixie validation for extra-repositories. Signed-off-by: Simon Beaudoin --- .github/workflows/pkg-build-reusable-workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pkg-build-reusable-workflow.yml b/.github/workflows/pkg-build-reusable-workflow.yml index 504f5242..4800d007 100644 --- a/.github/workflows/pkg-build-reusable-workflow.yml +++ b/.github/workflows/pkg-build-reusable-workflow.yml @@ -96,7 +96,7 @@ permissions: packages: read env: - DEBUSINE_ACTION_REF: main + DEBUSINE_ACTION_REF: dev/sbeaudoi-extra-repositories jobs: resolve: