Skip to content

Commit 7d869a7

Browse files
committed
Makefile: add Debian packaging targets
Add 'package' target to Makefile that, based on the 'GOOS', builds the platform-appropriate package. For now, support only binary .deb packages (corresponding to a 'GOOS' of 'linux'); if the 'GOOS' is unsupported, 'make' will exit with an error. The .deb packaging process is broken into three steps, each corresponding to a target in the Makefile: 1. Build the executables. 2. Copy the executables & any symlinks into the appropriate file structure for running 'dpkg-deb'. 3. Generate the control file, copy the maintainer script(s) [1], and build the package with 'dpkg-deb'. Additionally, the 'check-arch' and 'check-version' targets verify that the 'GOARCH' is supported for packaging on the platform and that a version string is set, respectively. In accordance with the 'project-layout' guidelines for the Makefile [2], most of the packaging logic outlined above lives in dedicated scripts. Best practice for the location of these scripts is somewhat vague, since it appears that both 'scripts/' [3] and 'build/package/' [4] would be valid choices. Go with the latter, putting the scripts in 'build/package' (if they will apply to more than one packaging mechanism) or a 'deb' subdirectory for Debian-specific configuration. [1] https://www.debian.org/doc/debian-policy/ap-flowcharts.html [2] https://github.com/golang-standards/project-layout/tree/master#scripts [3] https://github.com/golang-standards/project-layout/blob/master/scripts/README.md [4] https://github.com/golang-standards/project-layout/blob/master/build/README.md Signed-off-by: Victoria Dye <[email protected]>
1 parent be8f1ea commit 7d869a7

File tree

6 files changed

+252
-1
lines changed

6 files changed

+252
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/git-bundle-server
22
/git-bundle-web-server
33
/bin/
4+
/_dist/

.vscode/settings.json

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,24 @@
66
"editor.wordWrap": "off",
77
"files.trimTrailingWhitespace": true,
88
},
9+
"[makefile]": {
10+
"editor.detectIndentation": false,
11+
"editor.insertSpaces": false,
12+
"editor.tabSize": 8,
13+
"editor.wordWrap": "off",
14+
"files.trimTrailingWhitespace": true,
15+
},
16+
"[shellscript]": {
17+
"editor.detectIndentation": false,
18+
"editor.insertSpaces": false,
19+
"editor.tabSize": 8,
20+
"editor.wordWrap": "off",
21+
"files.trimTrailingWhitespace": true,
22+
},
923
"files.associations": {
10-
"*.md": "markdown"
24+
"*.md": "markdown",
25+
"*.sh": "shellscript",
26+
"prerm": "shellscript",
27+
"Makefile": "makefile"
1128
}
1229
}

Makefile

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,84 @@
11
# Default target
22
build:
33

4+
# Project metadata (note: to package, VERSION *must* be set by the caller)
5+
NAME := git-bundle-server
6+
VERSION :=
7+
PACKAGE_REVISION := 1
8+
49
# Helpful paths
510
BINDIR := $(CURDIR)/bin
11+
DISTDIR := $(CURDIR)/_dist
612

713
# Platform information
814
GOOS := $(shell go env GOOS)
915
GOARCH := $(shell go env GOARCH)
1016

17+
# Packaging information
18+
SUPPORTED_PACKAGE_GOARCHES := amd64 arm64
19+
PACKAGE_ARCH := $(GOARCH)
20+
1121
# Build targets
1222
.PHONY: build
1323
build:
1424
$(RM) -r $(BINDIR)
1525
@mkdir -p $(BINDIR)
1626
GOOS="$(GOOS)" GOARCH="$(GOARCH)" go build -o $(BINDIR) ./...
1727

28+
# Packaging targets
29+
.PHONY: check-arch
30+
check-arch:
31+
$(if $(filter $(GOARCH),$(SUPPORTED_PACKAGE_GOARCHES)), , \
32+
$(error cannot create package for GOARCH "$(GOARCH)"; \
33+
supported architectures are: $(SUPPORTED_PACKAGE_GOARCHES)))
34+
35+
.PHONY: check-version
36+
check-version:
37+
$(if $(VERSION), , $(error version is undefined))
38+
39+
ifeq ($(GOOS),linux)
40+
# Linux binary .deb file
41+
# Steps:
42+
# 1. Layout files in _dist/deb/root/ as they'll be installed (unlike MacOS
43+
# .pkg packages, symlinks created in the payload are preserved, so we
44+
# create them here to avoid doing so in a post-install step).
45+
# 2. Create the binary deb package in _dist/deb/.
46+
47+
# Platform-specific variables
48+
DEBDIR := $(DISTDIR)/deb
49+
DEB_FILENAME := $(DISTDIR)/$(NAME)_$(VERSION)-$(PACKAGE_REVISION)_$(PACKAGE_ARCH).deb
50+
51+
# Targets
52+
$(DEBDIR)/root: check-arch build
53+
@echo
54+
@echo "======== Formatting package contents ========"
55+
@build/package/layout-unix.sh --bindir="$(BINDIR)" \
56+
--include-symlinks \
57+
--output="$(DEBDIR)/root"
58+
59+
$(DEB_FILENAME): check-version $(DEBDIR)/root
60+
@echo
61+
@echo "======== Creating binary Debian package ========"
62+
@build/package/deb/pack.sh --payload="$(DEBDIR)/root" \
63+
--scripts="$(CURDIR)/build/package/deb/scripts" \
64+
--arch="$(PACKAGE_ARCH)" \
65+
--version="$(VERSION)" \
66+
--output="$(DEB_FILENAME)"
67+
68+
.PHONY: package
69+
package: $(DEB_FILENAME)
70+
71+
else
72+
# Packaging not supported for platform, exit with error.
73+
.PHONY: package
74+
package:
75+
$(error cannot create package for GOOS "$(GOOS)")
76+
77+
endif
78+
1879
# Cleanup targets
1980
.PHONY: clean
2081
clean:
2182
go clean ./...
2283
$(RM) -r $(BINDIR)
84+
$(RM) -r $(DISTDIR)

build/package/deb/pack.sh

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/bin/bash
2+
die () {
3+
echo "$*" >&2
4+
exit 1
5+
}
6+
7+
# Directories
8+
THISDIR="$( cd "$(dirname "$0")" ; pwd -P )"
9+
10+
# Local paths
11+
UNINSTALLER="$THISDIR/uninstall.sh"
12+
13+
# Parse script arguments
14+
for i in "$@"
15+
do
16+
case "$i" in
17+
--payload=*)
18+
DEBROOT="${i#*=}"
19+
shift # past argument=value
20+
;;
21+
--scripts=*)
22+
SCRIPT_DIR="${i#*=}"
23+
shift # past argument=value
24+
;;
25+
--arch=*)
26+
ARCH="${i#*=}"
27+
shift # past argument=value
28+
;;
29+
--version=*)
30+
VERSION="${i#*=}"
31+
shift # past argument=value
32+
;;
33+
--output=*)
34+
DEBOUT="${i#*=}"
35+
shift # past argument=value
36+
;;
37+
*)
38+
die "unknown option '$i'"
39+
;;
40+
esac
41+
done
42+
43+
# Perform pre-execution checks
44+
if [ -z "$DEBROOT" ]; then
45+
die "--payload was not set"
46+
elif [ ! -d "$DEBROOT" ]; then
47+
die "Could not find '$DEBROOT'. Did you run layout-unix.sh first?"
48+
fi
49+
if [ -z "$ARCH" ]; then
50+
die "--arch was not set"
51+
fi
52+
if [ -z "$VERSION" ]; then
53+
die "--version was not set"
54+
fi
55+
if [ -z "$DEBOUT" ]; then
56+
die "--output was not set"
57+
fi
58+
59+
# Exit as soon as any line fails
60+
set -e
61+
62+
# Cleanup old package
63+
if [ -e "$DEBOUT" ]; then
64+
echo "Deleting old package '$DEBOUT'..."
65+
rm -f "$DEBOUT"
66+
fi
67+
68+
CONTROLDIR="$DEBROOT/DEBIAN"
69+
70+
# Ensure the parent directory for the .deb exists
71+
mkdir -p "$(dirname "$DEBOUT")"
72+
73+
# Build .deb
74+
mkdir -m 755 -p "$CONTROLDIR"
75+
76+
# Create the debian control file
77+
cat >"$CONTROLDIR/control" <<EOF
78+
Package: git-bundle-server
79+
Version: $VERSION
80+
Section: vcs
81+
Priority: optional
82+
Architecture: $ARCH
83+
Depends:
84+
Maintainer: Git Bundle Server <[email protected]>
85+
Description: A self-hostable Git bundle server.
86+
EOF
87+
88+
# Copy the maintainer scripts, if they exist
89+
if [ -d "$SCRIPT_DIR" ]; then
90+
cp -R "$SCRIPT_DIR/." "$CONTROLDIR"
91+
fi
92+
93+
dpkg-deb -Zxz --build "$DEBROOT" "$DEBOUT"

build/package/deb/scripts/prerm

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Stop & cleanup the web server as the logged-in user
5+
# The XDG_RUNTIME_DIR is required for 'systemctl' to work, so we manually set it
6+
# to that of the logged-in user.
7+
LOGGED_IN_USER="${SUDO_USER:-${USER}}"
8+
LOGGED_IN_UID="$(sudo -u $LOGGED_IN_USER id -u)"
9+
sudo -u $LOGGED_IN_USER XDG_RUNTIME_DIR=/run/user/$LOGGED_IN_UID \
10+
/usr/local/git-bundle-server/bin/git-bundle-server web-server stop --remove
11+
12+
exit 0

build/package/layout-unix.sh

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#!/bin/bash
2+
die () {
3+
echo "$*" >&2
4+
exit 1
5+
}
6+
7+
# Parse script arguments
8+
for i in "$@"
9+
do
10+
case "$i" in
11+
--bindir=*)
12+
BINDIR="${i#*=}"
13+
shift # past argument=value
14+
;;
15+
--include-symlinks)
16+
INCLUDE_SYMLINKS=1
17+
shift # past argument
18+
;;
19+
--output=*)
20+
PAYLOAD="${i#*=}"
21+
shift # past argument=value
22+
;;
23+
*)
24+
die "unknown option '$i'"
25+
;;
26+
esac
27+
done
28+
29+
# Perform pre-execution checks
30+
if [ -z "$BINDIR" ]; then
31+
die "--bindir was not set"
32+
fi
33+
if [ -z "$PAYLOAD" ]; then
34+
die "--output was not set"
35+
fi
36+
37+
# Exit as soon as any line fails
38+
set -e
39+
40+
# Cleanup any old payload directory
41+
if [ -d "$PAYLOAD" ]; then
42+
echo "Cleaning old output directory '$PAYLOAD'..."
43+
rm -rf "$PAYLOAD"
44+
fi
45+
46+
# Ensure payload directory exists
47+
INSTALL_TO="$PAYLOAD/usr/local/git-bundle-server"
48+
mkdir -p "$INSTALL_TO"
49+
50+
# Copy built binaries
51+
echo "Copying binaries..."
52+
cp -R "$BINDIR/." "$INSTALL_TO/bin"
53+
54+
# Create symlinks
55+
if [ -n "$INCLUDE_SYMLINKS" ]; then
56+
LINK_TO="$PAYLOAD/usr/local/bin"
57+
mkdir -p "$LINK_TO"
58+
59+
echo "Creating symlinks..."
60+
for program in "$INSTALL_TO"/bin/*
61+
do
62+
ln -s -r "$program" "$LINK_TO/$(basename $program)"
63+
done
64+
fi
65+
66+
echo "Layout complete."

0 commit comments

Comments
 (0)