Try   HackMD

Note: Process in week 2 meant the process related to packaging best practices for multiple github repository and was meant for coordination. That process were replaced by the internal process of how to create debian packages.

Note: The process of creating debian packages are very flexible and upto each maintainer. Debian offers best practices and policies that must be followed, but there is no one way to do it. So for new maintainers is the biggest challange to overcome.

The bellow guide is based on following mainstream debian best practices, and were picked for simplicity and reproducibility in mind.

Creating debian packages process overview

Prerequisites

Setup docker container for creating/modifying deb package

  1. Install docker container for creating deb package, which setups the machine for .deb package development
   # Use the official Debian image as the base image
FROM debian:bookworm

# Update the package lists and install build-essential and zsh
RUN apt-get update && \
    apt-get install -y build-essential devscripts

# Debian maintainance tools
# Source: https://www.debian.org/doc/manuals/developers-reference/tools.html 
RUN apt-get update && \
    apt-get install -y dpkg-dev debconf fakeroot 

RUN apt-get update && \
    apt-get install -y lintian lintian-brush piuparts 
RUN apt-get update && \
    apt-get install -y diffoscope duck adequate i18nspector cme licensecheck blhc 
RUN apt-get update && \
    apt-get install -y debhelper dh-make 

RUN apt-get update && \
    apt-get install -y dupload dput 
RUN apt-get update && \
    apt-get install -y devscripts reportbug autotools-dev dpkg-repack alien dpkg-dev-el  
RUN apt-get update && \
    apt-get install -y dpkg-cross \
    debian-policy doc-debian developers-reference maint-guide packaging-tutorial how-can-i-help docbook-xml debiandoc-sgml debian-keyring debian-el
RUN apt-get update && \
    apt-get install -y autopkgtest
RUN apt-get update && \
    apt-get install -y debootstrap sbuild
RUN apt-get update && \
    apt-get install -y git-buildpackage   
RUN apt-get update && \
    apt-get install -y equivs       
RUN apt-get update && \
    apt-get install -y mc      
RUN apt-get update && \
    apt-get install -y vim nano       
RUN apt-get update && \
    apt-get install -y debmake      
RUN apt-get update && \
    apt-get install -y dgit    

# Optionally, you can set the working directory inside the container
# This is where you can copy your package source code and work on it
# For example:
WORKDIR /package

# Set non-root user and group
ARG USERNAME=debian
ARG USER_UID=1000
ARG USER_GID=$USER_UID

# Create a non-root user
RUN groupadd --gid $USER_GID $USERNAME \
    && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME

RUN adduser "$USERNAME" sbuild

# Set the non-root user as the default user for the container
USER $USERNAME

# Add the environment variables to the user's .zshrc file
RUN echo 'export DEBEMAIL="$EMAIL"' >> /home/$USERNAME/.bashrc
RUN echo 'export DEBFULLNAME="$FULLNAME"' >> /home/$USERNAME/.bashrc

RUN git config --global user.name "$EMAIL"
RUN git config --global user.email "$FULLNAME"

# Add the mc.sh initialization to zsh
RUN echo 'if [ -f /usr/lib/mc/mc.sh ]; then . /usr/lib/mc/mc.sh; fi' >> /home/$USERNAME/.bashrc

# Add the quilt alias and completions to zsh
RUN echo 'alias dquilt="quilt --quiltrc=${HOME}/.quiltrc-dpkg"' >> /home/$USERNAME/.bashrc
RUN echo '. /usr/share/bash-completion/completions/quilt' >> /home/$USERNAME/.bashrc
RUN echo 'complete -F _quilt_completion $_quilt_complete_opt dquilt' >> /home/$USERNAME/.bashrc


# Add the content for ~/.quiltrc-dpkg
COPY .quiltrc-dpkg /home/$USERNAME/.quiltrc-dpkg

# Set up configurations in ~/.devscripts
RUN echo 'DEBUILD_DPKG_BUILDPACKAGE_OPTS="-i -I -us -uc"' >> /home/$USERNAME/.devscripts
RUN echo 'DEBUILD_LINTIAN_OPTS="-i -I --show-overrides"' >> /home/$USERNAME/.devscripts
# TODO
# RUN echo 'DEBSIGN_KEYID="Your_GPG_keyID"' >> /home/$USERNAME/.devscripts


# Create the ~/.sbuildrc configuration file
COPY .sbuildrc /home/$USERNAME/.sbuildrc


# Set an entry point or command if you want the container to execute something by default
# For example, to start an interactive shell:
CMD ["bash"]

  1. Building the container
docker build -t debian-build-essentials .
  1. Running the container
docker run -e EMAIL="your.email.address@example.org" -e FULLNAME="Your Name"  -it --name debian_dev -v ~/debian/package:/package debian-build-essentials
  1. Entering the container
docker exec -it debian_dev bash

Creating a debian package

High level overview

  1. Acquire .tar.gz package
  2. Untar the package
  3. run debmake
  4. Modify files under the /debian newly created directory
  5. run debuild => this creates the package

The oversimplified method for the Debian packaging workflow can be summarized in 10 steps as follows.

  1. The upstream tarball is downloaded as the package-version.tar.gz file.
  2. The upstream tarball is untarred to create many files under the package-version/ directory.
  3. The upstream tarball is copied (or symlinked) to the particular filename packagename_version.orig.tar.gz.
  4. The Debian package specification files are added to the upstream source under the package-version/debian/ directory.
  5. The dpkg-buildpackage command (usually from its wrapper debuild or sbuild) is invoked in the package-version/ directory to make the Debian source and binary packages by invoking the debian/rules script.
  6. Check the quality of the Debian package with the lintian command. (recommended)
  7. Test the goodness of the generated Debian binary package manually by installing it and running its programs.
  8. After confirming the goodness, prepare files for the normal source-only upload to the Debian archive.
  9. Sign the package_version-revision.dsc and 'package_version-revision’_source.changes files with the debsign command using your private GPG key.
  10. Upload the set of the Debian source package files with the dput command to the Debian archive. Dgit also can be used, which is a wrapper around dgit.

Using git for packaging

The above process is quite cumbersome if it requires creating the debian directory each time when releasing packages with new version or applying patches, and simply meant to used on each maintainer machine.
The current debian trends recommends using git for package maintainers.

Here is the process overview of how these can be done with git-buildpackage

  • obtain .dsc file from packaging and create a new git repository where new releases can be tagged with branches
gbp import-dsc /path/to/package_0.1-1.dsc
  • using upstream repo
git clone <upstream-repo-url>
cd <upstream-repo-directory>
git checkout -b debian/latest
debmake
...modify files
git commit -a -m "Update package configuration"
gbp buildpackage /or debuild

Both ways will create upstream/latest and debian/latest branch, the main difference that the upstream branch in the second example the original code without the debian added directory.

For creating multiple packages this will be problematic, and both approach has pros and cons.

  1. Upstream option
    Pros:

    • original code can be tracked
      Cons:
    • would need to track with submodules all the repos built for debian packages
  2. Importing .tar.gz
    Pros:

    • either monorepo or single repo option can be selected
      Cons:
    • increase the size of the monorepo if pristine_tar is selected
    • would need to track original .tar.gz obtained

Testing packages [TODO]

Multiarch packages

Multiarch packages can be accomplished by using cowbuilder.
Here is a detailed article how to use it.

Questions and trouble areas

  • Testing packages
  • Automation
  • Reproducible builds
  • Monorepo vs multi-repo
  • complexity is hidden, debmake and debuild hides the underlying complexity of working package creation/modification

Resources: