-
Notifications
You must be signed in to change notification settings - Fork 0
/
debsync.sh
executable file
·122 lines (102 loc) · 4.1 KB
/
debsync.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/bin/bash
#
# Syncs debian packages from a github release to a local debian repo.
#
# Bail on errors.
set -e
set -o pipefail
# Base directory of the script and associated resources.
debsync_base=$(readlink -f "$(dirname "$0")")
# Local package repository directory. Packages are copied here.
package_repo='/usr/local/pkg/rkt'
# Runs a command in a sandboxed environment.
sandbox() {
local firejail_profile="${debsync_base}/firejail/$(basename $1).profile"
local firejail_cmd=
printf -v firejail_cmd '%q ' \
/usr/bin/firejail --quiet --profile="${firejail_profile}" -- "$@"
su -s /bin/bash -l -c "${firejail_cmd}" nobody
}
wget_safe() {
sandbox wget --quiet --output-document=- "$@" | head -c 512M
}
jq_safe() {
sandbox jq "$@" | head -c 10K
}
# Runs a command and only prints its diagnostic output on failure.
silence() {
local spoolfile=$(mktemp -p "${tmpdir}")
"$@" 2>"${spoolfile}" || (cat "$spoolfile" 1>&2 ; exit 1)
}
# Main script starts here.
# Set up a temporary directory.
tmpdir=$(mktemp -d)
trap 'rm -rf "${tmpdir}"' EXIT
# Download latest release information.
release_json="${tmpdir}/release.json"
wget_safe 'https://api.github.com/repos/coreos/rkt/releases/latest' \
> "${release_json}"
# Figure out the debian package file name.
raw_package_name=$(jq_safe -r '
.assets |
map(select((.name | startswith("rkt")) and
(.name | endswith("amd64.deb")))) |
.[0].name' < "${release_json}")
safe_package_name=$(echo "${raw_package_name}" | tr -d -c '[a-zA-Z0-9._\-]')
package_repo_file="${package_repo}/amd64/${safe_package_name}"
# Obtain the asset update timestamp.
asset_updated_at=$(jq_safe -r --arg name "${raw_package_name}" '
.assets | map(select(.name == $name)) | .[0].updated_at
' < "${release_json}")
# If the package file already exists, check whether it's been updated since
# we've last downloaded it.
if test -f "${package_repo_file}"; then
asset_timestamp=$(date -d "${asset_updated_at}" '+%s')
package_file_mtime=$(stat --format="%Y" "${package_repo_file}")
if test "${asset_timestamp}" -le "${package_file_mtime}"; then
# We already have this version, nothing to do.
exit 0
fi
fi
# Find the asset URLs corresponding to the debian package and its signature.
package_asset_url=$(jq_safe -r --arg name "${raw_package_name}" '
.assets | map(select(.name == $name)) | .[0].url
' < "${release_json}")
signature_asset_url=$(jq_safe -r --arg name "${raw_package_name}.asc" '
.assets | map(select(.name == $name)) | .[0].url
' < "${release_json}")
# Download the assets.
package_file="${tmpdir}/${safe_package_name}"
wget_safe --header="Accept: application/octet-stream" "${package_asset_url}" \
> "${package_file}"
signature_file="${tmpdir}/${safe_package_name}.asc"
wget_safe --header="Accept: application/octet-stream" "${signature_asset_url}" \
> "${signature_file}"
# Check signature.
silence gpg --no-verbose --batch --quiet --no-tty \
--no-default-keyring --keyring "${debsync_base}/coreos.gpg" --always-trust \
--verify "${signature_file}" "${package_file}"
# Move downloaded file to local package repository and set correct timestamp.
mkdir -p "${package_repo}/amd64"
mv "${package_file}" "${package_repo_file}"
touch -m -d "${asset_updated_at}" "${package_repo_file}"
# Update packages index.
(cd "${package_repo}" && silence dpkg-scanpackages -m . > "Packages")
# Produce an updated Release file.
pkgidx_sha256=$(sha256sum "${package_repo}/Packages" | cut -d \ -f 1)
pkgidx_size=$(wc -c "${package_repo}/Packages" | cut -d \ -f 1)
cat <<- EOF > "${package_repo}/Release"
Description: Local package repository generated by debsync.sh
Date: $(LANG=C date -Ru)
Architectures: amd64
Components: main contrib non-free
SHA256:
${pkgidx_sha256} ${pkgidx_size} Packages
EOF
# Clearsign the Release file.
rm -rf "${package_repo}/InRelease"
silence gpg --no-verbose --batch --quiet --no-tty \
--no-default-keyring --secret-keyring "${package_repo}/signing_key.gpg" \
--default-key A4057E20 --passphrase 1d564bd83f041fd29aea057f2bb7591d \
--clearsign --digest-algo SHA512 \
--output "${package_repo}/InRelease" "${package_repo}/Release"