@@ -160,6 +160,87 @@ runs:
160160 # subsequent cd operations might change the working directory.
161161 BUILD_DIR_ABS=$(realpath "../${{inputs.build-dir}}")
162162
163+ # Optional repo-local extension point for additional build-dependency apt repos.
164+ # Each non-empty, non-comment line in debian/extra-repositories.txt is passed
165+ # through to sbuild as --extra-repository "<line>".
166+ #
167+ # Supported entry formats:
168+ # deb [arch=arm64 ...] https://example.org/repo {suite} main
169+ # -> applies to all suites
170+ #
171+ # [noble,questing] deb [arch=arm64 ...] https://ppa.launchpadcontent.net/org/ppa/ubuntu noble main
172+ # -> applies only when target suite is listed
173+ #
174+ # Placeholders replaced with the runtime suite:
175+ # {suite}, {SUITE}, ${suite}, ${SUITE}, @suite@, @SUITE@
176+ EXTRA_REPOSITORIES_FILE="./debian/extra-repositories.txt"
177+ target_suite="${{inputs.suite}}"
178+ if [[ "$target_suite" == "unstable" ]]; then
179+ target_suite="sid"
180+ fi
181+ extra_repository_values=()
182+ extra_repository_args=()
183+ declare -A extra_repository_seen=()
184+
185+ if [[ -f "$EXTRA_REPOSITORIES_FILE" ]]; then
186+ echo "ℹ️ Found ${EXTRA_REPOSITORIES_FILE}; loading extra sbuild repositories"
187+
188+ while IFS= read -r raw_line || [[ -n "$raw_line" ]]; do
189+ line="$(printf '%s' "$raw_line" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
190+ [[ -n "$line" ]] || continue
191+ [[ "$line" =~ ^# ]] && continue
192+
193+ repo_entry="$line"
194+
195+ if [[ "$line" =~ ^\[([^][]+)\][[:space:]]+(.+)$ ]]; then
196+ suites_csv="${BASH_REMATCH[1]}"
197+ repo_entry="${BASH_REMATCH[2]}"
198+ include_entry=false
199+
200+ IFS=',' read -ra suite_filters <<< "$suites_csv"
201+ for suite_filter in "${suite_filters[@]}"; do
202+ suite_filter="$(printf '%s' "$suite_filter" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
203+ [[ -n "$suite_filter" ]] || continue
204+ if [[ "$suite_filter" == "$target_suite" || "$suite_filter" == "all" || "$suite_filter" == "*" ]]; then
205+ include_entry=true
206+ break
207+ fi
208+ done
209+
210+ if [[ "$include_entry" != true ]]; then
211+ echo "ℹ️ Skipping entry with suite filter [${suites_csv}] for target suite ${target_suite}"
212+ continue
213+ fi
214+ fi
215+
216+ repo_entry="${repo_entry//\$\{suite\}/$target_suite}"
217+ repo_entry="${repo_entry//\$\{SUITE\}/$target_suite}"
218+ repo_entry="${repo_entry//\{suite\}/$target_suite}"
219+ repo_entry="${repo_entry//\{SUITE\}/$target_suite}"
220+ repo_entry="${repo_entry//@suite@/$target_suite}"
221+ repo_entry="${repo_entry//@SUITE@/$target_suite}"
222+ repo_entry="$(printf '%s' "$repo_entry" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
223+ [[ -n "$repo_entry" ]] || continue
224+
225+ if [[ -n "${extra_repository_seen[$repo_entry]+x}" ]]; then
226+ continue
227+ fi
228+ extra_repository_seen["$repo_entry"]=1
229+
230+ extra_repository_values+=("$repo_entry")
231+ extra_repository_args+=(--extra-repository "$repo_entry")
232+ done < "$EXTRA_REPOSITORIES_FILE"
233+
234+ if (( ${#extra_repository_values[@]} > 0 )); then
235+ echo "ℹ️ Loaded ${#extra_repository_values[@]} extra repository entries:"
236+ printf ' - %s\n' "${extra_repository_values[@]}"
237+ else
238+ echo "ℹ️ ${EXTRA_REPOSITORIES_FILE} has no active entries (only blank/comment lines)"
239+ fi
240+ else
241+ echo "ℹ️ No ${EXTRA_REPOSITORIES_FILE} found; using default repositories only"
242+ fi
243+
163244 set +e
164245
165246 if [[ "$PREBUILT_MODE" == "true" ]]; then
@@ -201,6 +282,7 @@ runs:
201282 $lintian_flag \
202283 --build-dir "$BUILD_DIR_ABS" \
203284 --build-dep-resolver=apt \
285+ "${extra_repository_args[@]}" \
204286 "$DSC_FILE"
205287 else
206288 # ℹ️ Prebuilt mode + native source format: invoke sbuild directly —
@@ -212,25 +294,35 @@ runs:
212294 --dist=${{inputs.suite}} \
213295 $lintian_flag \
214296 --build-dir "$BUILD_DIR_ABS" \
215- --build-dep-resolver=apt
297+ --build-dep-resolver=apt \
298+ "${extra_repository_args[@]}"
216299 fi
217300
218301 else
219302 # ℹ️ Source build mode: use gbp buildpackage.
220303 # --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
221304 # ℹ️ chroot mode unshare is important to bypass privilege issues with the mounting
222305 # Host Architecture: The architecture for which the binaries are being built (invariably arm64).
306+ sbuild_builder_cmd=(
307+ sbuild
308+ --no-clean-source
309+ --dpkg-source-opt=--extend-diff-ignore=^\\.github
310+ --host=arm64
311+ --build=${{env.BUILD_ARCH}}
312+ --dist=${{inputs.suite}}
313+ "$lintian_flag"
314+ --build-dir
315+ "$BUILD_DIR_ABS"
316+ --build-dep-resolver=apt
317+ "${extra_repository_args[@]}"
318+ )
319+ printf -v sbuild_builder_escaped '%q ' "${sbuild_builder_cmd[@]}"
320+ sbuild_builder_escaped="${sbuild_builder_escaped% }"
321+
223322 gbp buildpackage \
224323 --git-no-pristine-tar \
225324 --git-ignore-branch \
226- --git-builder="sbuild --no-clean-source \
227- --dpkg-source-opt="--extend-diff-ignore=^\\.github" \
228- --host=arm64 \
229- --build=${{env.BUILD_ARCH}} \
230- --dist=${{inputs.suite}} \
231- $lintian_flag \
232- --build-dir $BUILD_DIR_ABS \
233- --build-dep-resolver=apt"
325+ --git-builder="$sbuild_builder_escaped"
234326 fi
235327
236328 RET=$?
0 commit comments