Skip to content

Commit 6c94290

Browse files
committed
Added script to publish to ppa launchpad
1 parent 8c86a4e commit 6c94290

3 files changed

Lines changed: 321 additions & 1 deletion

File tree

.github/workflows/publish-apt.yml

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
name: Publish to Launchpad PPA
2+
3+
on:
4+
release:
5+
types: [published]
6+
workflow_dispatch:
7+
inputs:
8+
tag:
9+
description: 'Release tag to publish'
10+
required: true
11+
type: string
12+
13+
permissions:
14+
contents: read
15+
16+
jobs:
17+
build-tarball:
18+
runs-on: ubuntu-latest
19+
outputs:
20+
version: ${{ steps.version.outputs.tag }}
21+
steps:
22+
- name: Determine version
23+
id: version
24+
env:
25+
INPUT_TAG: ${{ inputs.tag }}
26+
EVENT_NAME: ${{ github.event_name }}
27+
run: |
28+
if [ "${EVENT_NAME}" = "workflow_dispatch" ]; then
29+
echo "tag=${INPUT_TAG}" >> "$GITHUB_OUTPUT"
30+
else
31+
echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
32+
fi
33+
34+
- name: Download Linux native binaries from release
35+
env:
36+
VERSION: ${{ steps.version.outputs.tag }}
37+
REPO: ${{ github.repository }}
38+
run: |
39+
echo "Downloading crip binaries for version ${VERSION}"
40+
41+
curl -fsSL "https://github.com/${REPO}/releases/download/${VERSION}/crip-linux-amd64.tar.gz" -o crip-linux-amd64.tar.gz
42+
mkdir -p binary/amd64
43+
tar -xzf crip-linux-amd64.tar.gz -C binary/amd64
44+
45+
curl -fsSL "https://github.com/${REPO}/releases/download/${VERSION}/crip-linux-aarch64.tar.gz" -o crip-linux-aarch64.tar.gz
46+
mkdir -p binary/aarch64
47+
tar -xzf crip-linux-aarch64.tar.gz -C binary/aarch64
48+
49+
- name: Create orig tarball
50+
env:
51+
VERSION: ${{ steps.version.outputs.tag }}
52+
run: |
53+
SOURCE_DIR="crip-${VERSION}"
54+
mkdir -p "${SOURCE_DIR}/binaries"
55+
cp binary/amd64/crip "${SOURCE_DIR}/binaries/crip-amd64"
56+
cp binary/aarch64/crip "${SOURCE_DIR}/binaries/crip-arm64"
57+
tar -czf "crip_${VERSION}.orig.tar.gz" "${SOURCE_DIR}"
58+
59+
- name: Upload orig tarball and binaries
60+
uses: actions/upload-artifact@v4
61+
with:
62+
name: orig-tarball
63+
path: |
64+
crip_${{ steps.version.outputs.tag }}.orig.tar.gz
65+
binary/
66+
retention-days: 1
67+
68+
publish-ppa-primary:
69+
runs-on: ubuntu-latest
70+
needs: build-tarball
71+
steps:
72+
- name: Checkout repository
73+
uses: actions/checkout@v6
74+
75+
- name: Download orig tarball
76+
uses: actions/download-artifact@v4
77+
with:
78+
name: orig-tarball
79+
80+
- name: Install build dependencies
81+
run: |
82+
sudo apt-get update
83+
sudo apt-get install -y devscripts debhelper dput gpg
84+
85+
- name: Import GPG key
86+
id: gpg
87+
env:
88+
GPG_PASSPHRASE: ${{ secrets.LAUNCHPAD_GPG_PASSPHRASE }}
89+
run: |
90+
mkdir -p ~/.gnupg
91+
chmod 700 ~/.gnupg
92+
echo "allow-loopback-pinentry" > ~/.gnupg/gpg-agent.conf
93+
echo "allow-preset-passphrase" >> ~/.gnupg/gpg-agent.conf
94+
chmod 600 ~/.gnupg/gpg-agent.conf
95+
gpgconf --kill gpg-agent
96+
97+
echo "${{ secrets.LAUNCHPAD_GPG_PRIVATE_KEY }}" | gpg --batch --import
98+
GPG_FINGERPRINT=$(gpg --list-secret-keys --with-colons | awk -F: '/^fpr:/ {print $10; exit}')
99+
echo "key_id=${GPG_FINGERPRINT}" >> "$GITHUB_OUTPUT"
100+
101+
KEYGRIP=$(gpg --list-secret-keys --with-colons --with-keygrip | awk -F: '/^grp:/ {print $10; exit}')
102+
PASSPHRASE_HEX=$(echo -n "${GPG_PASSPHRASE}" | xxd -p -c 256)
103+
gpg-connect-agent "PRESET_PASSPHRASE ${KEYGRIP} -1 ${PASSPHRASE_HEX}" /bye
104+
105+
- name: Build source package and upload to PPA (with orig tarball)
106+
continue-on-error: true
107+
env:
108+
DEBFULLNAME: "Hakan Altindag"
109+
DEBEMAIL: ${{ secrets.LAUNCHPAD_EMAIL }}
110+
VERSION: ${{ needs.build-tarball.outputs.version }}
111+
GPG_KEY_ID: ${{ steps.gpg.outputs.key_id }}
112+
run: |
113+
chmod +x scripts/build-source-package.sh
114+
scripts/build-source-package.sh "${VERSION}" "noble" "${GPG_KEY_ID}" true
115+
116+
dput ppa:hakky554/apps "crip_${VERSION}-1~noble_source.changes"
117+
118+
publish-ppa-others:
119+
runs-on: ubuntu-latest
120+
needs: [build-tarball, publish-ppa-primary]
121+
if: always() && needs.build-tarball.result == 'success'
122+
strategy:
123+
fail-fast: false
124+
matrix:
125+
distro: [jammy, focal]
126+
steps:
127+
- name: Checkout repository
128+
uses: actions/checkout@v6
129+
130+
- name: Download orig tarball
131+
uses: actions/download-artifact@v4
132+
with:
133+
name: orig-tarball
134+
135+
- name: Install build dependencies
136+
run: |
137+
sudo apt-get update
138+
sudo apt-get install -y devscripts debhelper dput gpg
139+
140+
- name: Import GPG key
141+
id: gpg
142+
env:
143+
GPG_PASSPHRASE: ${{ secrets.LAUNCHPAD_GPG_PASSPHRASE }}
144+
run: |
145+
mkdir -p ~/.gnupg
146+
chmod 700 ~/.gnupg
147+
echo "allow-loopback-pinentry" > ~/.gnupg/gpg-agent.conf
148+
echo "allow-preset-passphrase" >> ~/.gnupg/gpg-agent.conf
149+
chmod 600 ~/.gnupg/gpg-agent.conf
150+
gpgconf --kill gpg-agent
151+
152+
echo "${{ secrets.LAUNCHPAD_GPG_PRIVATE_KEY }}" | gpg --batch --import
153+
GPG_FINGERPRINT=$(gpg --list-secret-keys --with-colons | awk -F: '/^fpr:/ {print $10; exit}')
154+
echo "key_id=${GPG_FINGERPRINT}" >> "$GITHUB_OUTPUT"
155+
156+
KEYGRIP=$(gpg --list-secret-keys --with-colons --with-keygrip | awk -F: '/^grp:/ {print $10; exit}')
157+
PASSPHRASE_HEX=$(echo -n "${GPG_PASSPHRASE}" | xxd -p -c 256)
158+
gpg-connect-agent "PRESET_PASSPHRASE ${KEYGRIP} -1 ${PASSPHRASE_HEX}" /bye
159+
160+
- name: Build source package and upload to PPA (without orig tarball)
161+
env:
162+
DEBFULLNAME: "Hakan Altindag"
163+
DEBEMAIL: ${{ secrets.LAUNCHPAD_EMAIL }}
164+
VERSION: ${{ needs.build-tarball.outputs.version }}
165+
DISTRO: ${{ matrix.distro }}
166+
GPG_KEY_ID: ${{ steps.gpg.outputs.key_id }}
167+
run: |
168+
chmod +x scripts/build-source-package.sh
169+
scripts/build-source-package.sh "${VERSION}" "${DISTRO}" "${GPG_KEY_ID}" false
170+
171+
dput ppa:hakky554/apps "crip_${VERSION}-1~${DISTRO}_source.changes"

README.MD

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ The executables are available for download in the [Releases](https://github.com/
4949
- Mac OS X & Linux - Homebrew 🍺
5050
- Run `brew install crip`
5151
- Mac OS X & Linux - Homebrew with native binary 🍺
52-
- Run `brew tap hakky54/crip && brew install crip`
52+
- Run `brew install hakky54/homebrew-apps/crip`
53+
- Linux - Debian/Ubuntu (apt) 📦
54+
- Run `sudo add-apt-repository ppa:hakky554/apps && sudo apt-get install crip -t 'o=LP-PPA-hakky554-apps'`
5355
- Linux & Windows
5456
- Download the latest binary here: [Releases](https://github.com/Hakky54/certificate-ripper/releases)
5557

scripts/build-source-package.sh

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Builds a Debian source package for Launchpad PPA upload.
4+
# The package ships pre-built native binaries for amd64 and arm64.
5+
#
6+
# Usage: ./scripts/build-source-package.sh <version> <distro> <gpg_key_id> [include_orig]
7+
#
8+
# The optional include_orig flag (true/false, default true) controls whether the
9+
# orig tarball is included in the upload (-sa) or omitted (-sd). Launchpad requires
10+
# the orig tarball to be identical across all uploads for the same upstream version,
11+
# so only the first distro upload should include it; subsequent distros should set
12+
# this to "false" so Launchpad reuses the tarball already on file.
13+
#
14+
# Example: ./scripts/build-source-package.sh 2.7.1 noble ABC123DEF456 true
15+
# ./scripts/build-source-package.sh 2.7.1 jammy ABC123DEF456 false
16+
17+
set -euo pipefail
18+
19+
VERSION="${1:?Usage: build-source-package.sh <version> <distro> <gpg_key_id> [include_orig]}"
20+
DISTRO="${2:?Usage: build-source-package.sh <version> <distro> <gpg_key_id> [include_orig]}"
21+
GPG_KEY_ID="${3:?Usage: build-source-package.sh <version> <distro> <gpg_key_id> [include_orig]}"
22+
INCLUDE_ORIG="${4:-true}"
23+
24+
PACKAGE_NAME="crip"
25+
SOURCE_DIR="${PACKAGE_NAME}-${VERSION}"
26+
ORIG_TARBALL="${PACKAGE_NAME}_${VERSION}.orig.tar.gz"
27+
28+
echo "==> Building source package for ${PACKAGE_NAME} ${VERSION} (${DISTRO})"
29+
30+
# Create source directory with pre-built binaries
31+
mkdir -p "${SOURCE_DIR}/binaries"
32+
cp binary/amd64/crip "${SOURCE_DIR}/binaries/crip-amd64"
33+
cp binary/aarch64/crip "${SOURCE_DIR}/binaries/crip-arm64"
34+
35+
# Reuse existing orig tarball if present (all distros must share the same one for Launchpad)
36+
if [ ! -f "${ORIG_TARBALL}" ]; then
37+
echo "==> Creating orig tarball ${ORIG_TARBALL}"
38+
tar -czf "${ORIG_TARBALL}" "${SOURCE_DIR}"
39+
fi
40+
41+
# Create debian packaging directory
42+
mkdir -p "${SOURCE_DIR}/debian/source"
43+
44+
# debian/source/format
45+
echo "3.0 (quilt)" > "${SOURCE_DIR}/debian/source/format"
46+
47+
# debian/compat
48+
echo "12" > "${SOURCE_DIR}/debian/compat"
49+
50+
# debian/control
51+
cat > "${SOURCE_DIR}/debian/control" << 'EOF'
52+
Source: crip
53+
Section: utils
54+
Priority: optional
55+
Maintainer: Hakan Altindag <hakangoudberg@hotmail.com>
56+
Build-Depends: debhelper (>= 12)
57+
Standards-Version: 4.5.1
58+
Homepage: https://github.com/Hakky54/certificate-ripper
59+
60+
Package: crip
61+
Architecture: amd64 arm64
62+
Depends: ${misc:Depends}
63+
Description: CLI tool to extract server certificates
64+
Certificate Ripper is a CLI tool to extract server certificates from
65+
HTTPS, WSS, FTPS, IMAPS, and SMTPS servers. Extracted certificates
66+
can be printed in human-readable or PEM format, and exported to
67+
PKCS12, JKS, DER, or PEM files.
68+
EOF
69+
70+
# debian/rules
71+
cat > "${SOURCE_DIR}/debian/rules" << 'RULES'
72+
#!/usr/bin/make -f
73+
%:
74+
dh $@
75+
76+
override_dh_auto_build:
77+
# Nothing to build, we ship pre-compiled native binaries
78+
79+
override_dh_auto_install:
80+
install -D -m 755 binaries/crip-$(DEB_HOST_ARCH) debian/crip/usr/bin/crip
81+
82+
override_dh_strip:
83+
# Skip stripping, binary is a GraalVM native-image
84+
85+
override_dh_shlibdeps:
86+
# Skip shared library dependency detection
87+
RULES
88+
chmod 755 "${SOURCE_DIR}/debian/rules"
89+
90+
# debian/changelog
91+
cat > "${SOURCE_DIR}/debian/changelog" << EOF
92+
crip (${VERSION}-1~${DISTRO}) ${DISTRO}; urgency=medium
93+
94+
* Release ${VERSION}
95+
96+
-- ${DEBFULLNAME} <${DEBEMAIL}> $(date -R)
97+
EOF
98+
99+
# debian/copyright
100+
cat > "${SOURCE_DIR}/debian/copyright" << 'EOF'
101+
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
102+
Upstream-Name: certificate-ripper
103+
Upstream-Contact: Hakan Altindag <hakangoudberg@hotmail.com>
104+
Source: https://github.com/Hakky54/certificate-ripper
105+
106+
Files: *
107+
Copyright: 2021 Thunderberry
108+
License: Apache-2.0
109+
110+
License: Apache-2.0
111+
Licensed under the Apache License, Version 2.0 (the "License");
112+
you may not use this file except in compliance with the License.
113+
You may obtain a copy of the License at
114+
.
115+
https://www.apache.org/licenses/LICENSE-2.0
116+
.
117+
Unless required by applicable law or agreed to in writing, software
118+
distributed under the License is distributed on an "AS IS" BASIS,
119+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120+
See the License for the specific language governing permissions and
121+
limitations under the License.
122+
EOF
123+
124+
# debian/source/lintian-overrides (pre-built native binaries have no source)
125+
cat > "${SOURCE_DIR}/debian/source/lintian-overrides" << 'EOF'
126+
crip source: source-is-missing [binaries/crip-amd64]
127+
crip source: source-is-missing [binaries/crip-arm64]
128+
EOF
129+
130+
# Build the unsigned source package (-d skips build dependency checks since we ship pre-built binaries)
131+
# -sa includes the orig tarball (for the first distro upload)
132+
# -sd omits it (for subsequent distros, Launchpad reuses the one already uploaded)
133+
if [ "${INCLUDE_ORIG}" = "true" ]; then
134+
SA_FLAG="-sa"
135+
else
136+
SA_FLAG="-sd"
137+
fi
138+
139+
cd "${SOURCE_DIR}"
140+
debuild -S ${SA_FLAG} -d -us -uc
141+
cd ..
142+
143+
# Sign the source package (gpg-agent has the passphrase pre-cached from the workflow)
144+
debsign -k"${GPG_KEY_ID}" "${PACKAGE_NAME}_${VERSION}-1~${DISTRO}_source.changes"
145+
146+
echo "==> Source package built successfully for ${DISTRO}"
147+

0 commit comments

Comments
 (0)