-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(build-debian): Use docker to manually run build and prepare step…
…s and add tests (#28) As underlined in ubuntu/authd#130 (comment) using `jtdor/build-deb-action` for building debian packages has some problems that are yet not clear, and it also does not seem to properly support building non-native packages. As per this, given that the code needed for handling the build inside a simpler docker container is quite small, I've moved the build to manual handling which allows us some more control over the steps at the cost of being a bit more verbose. As bonus: - We now only build as user (not the sources, since there's no much point) - All the network traffic is totally blocked for the builder user (not just HTTPS) - ~~`DEB_BUILD_OPTIONS` can be customized for special builds (e.g. `nocheck`)~~ - Version uses actual distro version I've added some commits from #22, but not included the lintian build yet (that I've ready [here](3v1n0@1b72205)) not to make this PR harder to check, but also because I think those could instead be part of another action to allow more parallelization when used. By doing this change, not only both test cases pass, but also authd is correctly built: ubuntu/authd#130 (e.g. https://github.com/ubuntu/authd/actions/runs/8044158864) UDENG-2439
- Loading branch information
Showing
2 changed files
with
260 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
name: Test build debian package | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
paths: | ||
- gh-actions/common/build-debian/** | ||
- .github/workflows/test-build-deb* | ||
pull_request: | ||
|
||
env: | ||
DEBIAN_FRONTEND: noninteractive | ||
DEBCONF_NONINTERACTIVE_SEEN: true | ||
|
||
jobs: | ||
build_native_deb: | ||
name: Test build native debian package | ||
runs-on: ubuntu-latest | ||
outputs: | ||
pkg-name: ${{ env.PKG_NAME }} | ||
pkg-version: ${{ env.PKG_VERSION }} | ||
|
||
steps: | ||
- name: Install dependencies | ||
run: | | ||
sudo apt update | ||
sudo apt install ubuntu-dev-tools | ||
- name: Get and prepare package source | ||
run: | | ||
set -eu | ||
echo "::group::Get source" | ||
pull-lp-source --download-only hello | ||
dpkg-source -x hello*.dsc hello-src | ||
rm -rf hello_* | ||
mv -v hello-src/* . | ||
echo "::endgroup::" | ||
echo "::group::Mark package as a native package" | ||
echo "3.0 (native)" > debian/source/format | ||
dch -v$(dpkg-parsechangelog -S Version | cut -f1 -d-).1 \ | ||
"Mark as native package" | ||
echo "::endgroup::" | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
with: | ||
path: .source | ||
|
||
- name: Build package | ||
uses: ./.source/gh-actions/common/build-debian | ||
with: | ||
docker-image: ubuntu:devel | ||
|
||
build_source_deb: | ||
name: Test build quilt debian package | ||
runs-on: ubuntu-latest | ||
outputs: | ||
pkg-name: ${{ env.PKG_NAME }} | ||
pkg-version: ${{ env.PKG_VERSION }} | ||
source-pkg: ${{ steps.build-debian-source-package-upload-step.outputs.artifact-url }} | ||
binaries: ${{ steps.build-debian-binary-packages-upload-step.outputs.artifact-url }} | ||
|
||
steps: | ||
- name: Install dependencies | ||
run: | | ||
sudo apt update | ||
sudo apt install ubuntu-dev-tools | ||
- name: Get package source | ||
run: | | ||
set -eu | ||
pull-lp-source --download-only hello | ||
dpkg-source -x hello*.dsc hello-src | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
with: | ||
path: .source | ||
|
||
- name: Build package | ||
uses: ./.source/gh-actions/common/build-debian | ||
with: | ||
source-dir: ./hello-src | ||
docker-image: ubuntu:devel | ||
extra-source-build-deps: '' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,14 +12,19 @@ inputs: | |
token: | ||
required: false | ||
description: If provided, used for git authentication in the source build | ||
extra-source-build-deps: | ||
description: A list of extra build dependencies required during source build. | ||
required: false | ||
# FIXME: this should default to '', but we don't want to break job depending on us for now | ||
default: 'ca-certificates git' | ||
|
||
|
||
# The process: | ||
# 1. We build the source package in a docker container with ca-certificates installed and thus, | ||
# a useful internet connection. | ||
# 1. We build the source package in a docker container. If ca-certificates are | ||
# installed via extra-source-build-deps we can have a useful internet connection. | ||
# 2. We the extract the source package. | ||
# 3. We build the .deb from the source package, in a container without ca-certificates (unless it | ||
# is added as a build dependency), hence without a useful internet connection. | ||
# 3. We build the .deb from the source package, in a container without internet | ||
# kind of internet connection. | ||
# | ||
# To help with debugging, here are the processes and the directories they takes place in: | ||
# | ||
|
@@ -44,71 +49,204 @@ runs: | |
- name: Set up source package build | ||
shell: bash | ||
run: | | ||
echo "::group::Create local version with commit and docker container" | ||
set -eu | ||
echo "::group::Install devscripts" | ||
DEBIAN_FRONTEND=noninteractive sudo apt update | ||
DEBIAN_FRONTEND=noninteractive sudo apt install -y devscripts | ||
echo "::endgroup::" | ||
echo "::group::Append commit SHA to local version" | ||
cd '${{ inputs.source-dir }}' | ||
sanitized_docker=$( echo "${{ inputs.docker-image }}" | sed 's/://' ) | ||
debchange --local "+${sanitized_docker}+${{ github.sha }}" "Github build. Job id: ${{ github.run_id }}. Attempt: ${{ github.run_number }}." | ||
# Short commit to avoid "package-has-long-file-name" | ||
echo VERSION_REF=$(date +'%y%m%d').${{ github.run_number }}.$(echo ${{ github.sha }} | cut -c1-8) >> $GITHUB_ENV | ||
echo DEBFULLNAME="GitHub actions runner" >> $GITHUB_ENV | ||
echo DEBEMAIL="[email protected]" >> $GITHUB_ENV | ||
if git status --porcelain &>/dev/null; then | ||
echo DEBFULLNAME="$(git log -1 --format='%an' HEAD) - GH Action" >> $GITHUB_ENV | ||
echo DEBEMAIL="$(git log -1 --format='%ae' HEAD)" >> $GITHUB_ENV | ||
fi | ||
echo "::endgroup::" | ||
- name: Prepare source package | ||
uses: kohlerdominik/[email protected] | ||
with: | ||
image: ${{ inputs.docker-image }} | ||
environment: | | ||
DEBIAN_FRONTEND=noninteractive | ||
DEBFULLNAME=${{ env.DEBFULLNAME }} | ||
DEBEMAIL=${{ env.DEBEMAIL }} | ||
volumes: ${{ github.workspace }}:${{ github.workspace }} | ||
workdir: ${{ github.workspace }}/${{ inputs.source-dir }} | ||
shell: bash | ||
run: | | ||
echo "::group::Update builder instance and install dependencies" | ||
set -eu | ||
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/90aptyes | ||
apt update | ||
apt install devscripts lsb-release | ||
echo "::endgroup::" | ||
echo "::group::Update debian package changelog" | ||
dch --local "+git${{ env.VERSION_REF }}~$(lsb_release -r -s)." \ | ||
"Github build. Run id: ${{ github.run_id }}. Run number: ${{ github.run_number }}." \ | ||
--distribution "$(lsb_release -c -s)" | ||
dpkg-parsechangelog | ||
echo "::endgroup::" | ||
- name: Parse package source info | ||
shell: bash | ||
run: | | ||
echo "::group::Parsing name and version" | ||
set -eu | ||
cd '${{ inputs.source-dir }}' | ||
echo PKG_NAME="$( dpkg-parsechangelog --show-field source )" >> $GITHUB_ENV | ||
echo PKG_VERSION="$( dpkg-parsechangelog --show-field version )" >> $GITHUB_ENV | ||
cd - | ||
echo "::endgroup::" | ||
echo "::group::Prepare source build" | ||
echo SOURCE_OUTPUT_DIR="$( mktemp --directory --tmpdir=. )" >> $GITHUB_ENV | ||
echo SOURCE_OUTPUT_DIR="$( mktemp --directory --tmpdir="${PWD}" )" >> $GITHUB_ENV | ||
echo "::endgroup::" | ||
- name: Build source package | ||
uses: jtdor/build-deb-action@v1 | ||
uses: kohlerdominik/docker-run-action@v2.0.0 | ||
with: | ||
source-dir: ${{ inputs.source-dir }} | ||
artifacts-dir: ${{ env.SOURCE_OUTPUT_DIR }} | ||
docker-image: ${{ inputs.docker-image }} | ||
buildpackage-opts: --build=source | ||
extra-build-deps: ca-certificates git | ||
before-build-hook: | | ||
image: ${{ inputs.docker-image }} | ||
environment: | | ||
DEBIAN_FRONTEND=noninteractive | ||
volumes: ${{ github.workspace }}:${{ github.workspace }} | ||
workdir: ${{ github.workspace }}/${{ inputs.source-dir }} | ||
shell: bash | ||
run: | | ||
echo "::group::Update builder instance" | ||
set -eu | ||
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/90aptyes | ||
apt update | ||
apt dist-upgrade | ||
echo "::endgroup::" | ||
echo "::group::Install build dependencies" | ||
apt build-dep . | ||
if [ -n "${{ inputs.extra-source-build-deps }}" ]; then | ||
# Install extra packages for build-deps, to allow downloading vendored sources | ||
deps=(${{ inputs.extra-source-build-deps }}) | ||
apt install ${deps[@]} | ||
fi | ||
echo "::endgroup::" | ||
if command -v git &> /dev/null; then | ||
git config --system --add safe.directory "${{ github.workspace }}" | ||
fi | ||
GITHUB_TOKEN="${{ inputs.token }}" | ||
if [ -n "${GITHUB_TOKEN}" ]; then | ||
git config --system url."https://api:${GITHUB_TOKEN}@github.com/".insteadOf "https://github.com/" | ||
fi | ||
echo "::group::Build debian source package" | ||
dpkg-buildpackage -D -S --sanitize-env | ||
echo "::endgroup::" | ||
mv -v ../"${{ env.PKG_NAME }}_"* "${{ env.SOURCE_OUTPUT_DIR }}" | ||
- name: Uploading source packages | ||
uses: actions/upload-artifact@v4 | ||
id: build-debian-source-package-upload-step | ||
with: | ||
name: ${{ env.PKG_NAME }}_${{ env.PKG_VERSION }}-debian-source | ||
path: ${{ env.SOURCE_OUTPUT_DIR }}/ | ||
if-no-files-found: error | ||
|
||
- name: Set up package build | ||
shell: bash | ||
run: | | ||
echo "::group::Create build input directory" | ||
set -eu | ||
echo "::group::Create build input directory" | ||
# Appending /source because 'dpkg-source --extract' needs the output directory to be non-existent | ||
BUILD_INPUT_DIR="$( mktemp --directory --tmpdir='.' )/source" | ||
BUILD_INPUT_BASEDIR="$( mktemp --directory --tmpdir="${PWD}" )" | ||
echo BUILD_INPUT_BASEDIR="${BUILD_INPUT_BASEDIR}" >> $GITHUB_ENV | ||
BUILD_INPUT_DIR="${BUILD_INPUT_BASEDIR}/source" | ||
echo BUILD_INPUT_DIR="${BUILD_INPUT_DIR}" >> $GITHUB_ENV | ||
echo "::endgroup::" | ||
echo "::group::Create build output directory" | ||
echo BUILD_OUTPUT_DIR="$( mktemp --directory --tmpdir='.' )" >> $GITHUB_ENV | ||
echo BUILD_OUTPUT_DIR="$( mktemp --directory --tmpdir="${PWD}" )" >> $GITHUB_ENV | ||
echo "::endgroup::" | ||
echo "::group::Extract source package" | ||
BUILD_INPUT_DIR=$(realpath "${BUILD_INPUT_DIR}") | ||
cd ${{ env.SOURCE_OUTPUT_DIR }} | ||
dpkg-source --extract *.dsc "${BUILD_INPUT_DIR}" | ||
cd - | ||
dpkg-source --extract ${{ env.PKG_NAME }}_${{ env.PKG_VERSION }}.dsc "${BUILD_INPUT_DIR}" | ||
echo "::endgroup::" | ||
- name: Build package | ||
uses: jtdor/build-deb-action@v1 | ||
- name: Build packages | ||
uses: kohlerdominik/[email protected] | ||
with: | ||
artifacts-dir: ${{ env.BUILD_OUTPUT_DIR }} | ||
source-dir: ${{ env.BUILD_INPUT_DIR }} | ||
docker-image: ${{ inputs.docker-image }} | ||
image: ${{ inputs.docker-image }} | ||
options: --cap-add=NET_ADMIN | ||
environment: | | ||
DEBIAN_FRONTEND=noninteractive | ||
workdir: ${{ env.BUILD_INPUT_DIR }} | ||
volumes: | | ||
${{ env.BUILD_INPUT_BASEDIR }}:${{ env.BUILD_INPUT_BASEDIR }} | ||
${{ env.BUILD_OUTPUT_DIR }}:${{ env.BUILD_OUTPUT_DIR }} | ||
shell: bash | ||
run: | | ||
echo "::group::Update builder instance" | ||
set -eu | ||
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/90aptyes | ||
apt update | ||
apt dist-upgrade | ||
echo "::endgroup::" | ||
echo "::group::Create build user" | ||
apt install adduser | ||
apt-mark auto adduser | ||
adduser --disabled-password --gecos "" builder | ||
chown builder:builder .. -R | ||
echo "::endgroup::" | ||
echo "::group::Fully disable internet access for user" | ||
apt install iptables | ||
apt-mark auto iptables | ||
iptables -A OUTPUT -m owner --uid-owner $(id -u builder) -d 127.0.0.1 -j ACCEPT | ||
iptables -A OUTPUT -m owner --uid-owner $(id -u builder) -j DROP | ||
echo "::endgroup::" | ||
echo "::group::Cleanup unneeded packages" | ||
apt autoremove | ||
echo "::endgroup::" | ||
echo "::group::Install fakeroot" | ||
apt install fakeroot | ||
echo "::endgroup::" | ||
echo "::group::Install build dependencies" | ||
apt build-dep . | ||
echo "::endgroup::" | ||
echo "::group::Build debian packages" | ||
runuser -u builder -- dpkg-buildpackage -D -b --sanitize-env | ||
echo "::endgroup::" | ||
mv -v ../*"_${{ env.PKG_VERSION }}_"*.deb "${{ env.BUILD_OUTPUT_DIR }}" | ||
echo "::group::Show binaries information" | ||
for i in "${{ env.BUILD_OUTPUT_DIR }}"/*.deb; do | ||
echo "$(basename "$i")" | ||
dpkg --info "$i" | ||
dpkg --contents "$i" | ||
done | ||
echo "::endgroup::" | ||
- name: Upload artifacts | ||
id: build-debian-binary-packages-upload-step | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: ${{ env.PKG_NAME }}_${{ env.PKG_VERSION }} | ||
name: ${{ env.PKG_NAME }}_${{ env.PKG_VERSION }}-debian-packages | ||
path: ${{ env.BUILD_OUTPUT_DIR }}/ | ||
if-no-files-found: error |