Skip to content

Commit 653dde5

Browse files
committed
Support deb src
1 parent 726648b commit 653dde5

6 files changed

Lines changed: 972 additions & 1 deletion

File tree

bin/build-deb.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// use dotenv to load environment variables from .env file
2+
// and provide proper envs to build-deb.sh, we could load data/electerm-github-release.json to get data needed
3+
import fs from 'fs'
4+
import path from 'path'
5+
import { spawn } from 'child_process'
6+
import { fileURLToPath } from 'url'
7+
import 'dotenv/config'
8+
9+
const __filename = fileURLToPath(import.meta.url)
10+
const __dirname = path.dirname(__filename)
11+
const PROJECT_ROOT = path.dirname(__dirname)
12+
const RELEASE_DATA_FILE = path.join(PROJECT_ROOT, 'data', 'electerm-github-release.json')
13+
const BUILD_DEB_SCRIPT = path.join(PROJECT_ROOT, 'bin', 'build-deb.sh')
14+
const VERCEL_JSON_FILE = path.join(PROJECT_ROOT, 'vercel.json')
15+
16+
async function buildDeb () {
17+
console.log('Loading release data from:', RELEASE_DATA_FILE)
18+
19+
// Load release data
20+
const releaseData = JSON.parse(fs.readFileSync(RELEASE_DATA_FILE, 'utf8'))
21+
const release = releaseData.release
22+
23+
// Find the .deb asset for amd64
24+
const debAsset = release.assets.find(asset =>
25+
asset.name.includes('.deb') && asset.name.includes('amd64')
26+
)
27+
28+
if (!debAsset) {
29+
throw new Error('No .deb asset found for amd64 architecture')
30+
}
31+
32+
console.log('Found .deb asset:', debAsset.name)
33+
34+
// Prepare environment variables
35+
const env = {
36+
...process.env,
37+
GPG_KEY_ID: process.env.GPG_KEY_ID || '',
38+
GPG_PRIVATE_KEY: process.env.GPG_PRIVATE_KEY || '',
39+
RELEASE_TAG: release.tag_name,
40+
RELEASE_DATE: release.published_at,
41+
DEB_ASSET_NAME: debAsset.name,
42+
DEB_ASSET_URL: debAsset.browser_download_url
43+
}
44+
45+
// Pass DEB_FILE_PATH if it exists
46+
if (process.env.DEB_FILE_PATH) {
47+
env.DEB_FILE_PATH = process.env.DEB_FILE_PATH
48+
}
49+
50+
console.log('Environment variables prepared:')
51+
console.log('- RELEASE_TAG:', env.RELEASE_TAG)
52+
console.log('- RELEASE_DATE:', env.RELEASE_DATE)
53+
console.log('- DEB_ASSET_NAME:', env.DEB_ASSET_NAME)
54+
console.log('- DEB_ASSET_URL:', env.DEB_ASSET_URL)
55+
if (env.DEB_FILE_PATH) {
56+
console.log('- DEB_FILE_PATH:', env.DEB_FILE_PATH)
57+
}
58+
59+
// Run build-deb.sh script
60+
console.log('Running build-deb.sh script...')
61+
62+
const buildProcess = spawn('bash', [BUILD_DEB_SCRIPT], {
63+
env,
64+
stdio: 'inherit'
65+
})
66+
67+
buildProcess.on('close', (code) => {
68+
if (code === 0) {
69+
console.log('✅ Debian repository build completed successfully!')
70+
71+
// Update vercel.json with rewrite rules
72+
updateVercelRewriteRules(release.tag_name, debAsset.name)
73+
} else {
74+
console.error('❌ Debian repository build failed with code:', code)
75+
process.exit(1)
76+
}
77+
})
78+
79+
buildProcess.on('error', (error) => {
80+
console.error('❌ Failed to start build process:', error)
81+
process.exit(1)
82+
})
83+
}
84+
85+
function updateVercelRewriteRules (releaseTag, debFileName) {
86+
console.log('Updating Vercel rewrite rules...')
87+
88+
// Read current vercel.json
89+
let vercelConfig = {}
90+
if (fs.existsSync(VERCEL_JSON_FILE)) {
91+
vercelConfig = JSON.parse(fs.readFileSync(VERCEL_JSON_FILE, 'utf8'))
92+
}
93+
94+
// Ensure rewrites array exists
95+
if (!vercelConfig.rewrites) {
96+
vercelConfig.rewrites = []
97+
}
98+
99+
// Remove existing electerm deb rewrite rules
100+
vercelConfig.rewrites = vercelConfig.rewrites.filter(rewrite =>
101+
!rewrite.source.includes('/deb/pool/main/e/electerm/')
102+
)
103+
104+
// Add new rewrite rule for the current release
105+
const newRewrite = {
106+
source: `/deb/pool/main/e/electerm/${debFileName}`,
107+
destination: `https://gh-proxy.com/https://github.com/electerm/electerm/releases/download/${releaseTag}/${debFileName}`
108+
}
109+
110+
vercelConfig.rewrites.push(newRewrite)
111+
112+
// Write updated vercel.json
113+
fs.writeFileSync(VERCEL_JSON_FILE, JSON.stringify(vercelConfig, null, 2) + '\n')
114+
115+
console.log('✅ Updated vercel.json with rewrite rule:')
116+
console.log(` ${newRewrite.source} -> ${newRewrite.destination}`)
117+
}
118+
119+
// Run the build process
120+
buildDeb()

bin/build-deb.sh

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
#!/bin/bash
2+
3+
# Build script for creating Debian repository
4+
# This script uses public as the root folder, public/deb as deb src folder
5+
6+
set -e
7+
8+
echo "Starting Debian repository build process..."
9+
10+
# Get the script directory
11+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
13+
PUBLIC_DIR="$PROJECT_ROOT/public"
14+
DEB_DIR="$PUBLIC_DIR/deb"
15+
SRC_DEB_BUILD="$PROJECT_ROOT/src/static/deb-build"
16+
17+
echo "Script directory: $SCRIPT_DIR"
18+
echo "Project root: $PROJECT_ROOT"
19+
echo "Public directory: $PUBLIC_DIR"
20+
echo "Deb directory: $DEB_DIR"
21+
echo "Source directory: $SRC_DEB_BUILD"
22+
23+
# Check if source directory exists
24+
if [ ! -d "$SRC_DEB_BUILD" ]; then
25+
echo "Error: Source directory $SRC_DEB_BUILD does not exist"
26+
exit 1
27+
fi
28+
29+
# Create proper Debian repository structure
30+
mkdir -p "$DEB_DIR/dists/stable/main/binary-amd64"
31+
mkdir -p "$DEB_DIR/pool/main/e/electerm"
32+
33+
# Copy static files to the deb root
34+
echo "Copying static files from $SRC_DEB_BUILD to $DEB_DIR..."
35+
if [ -f "$SRC_DEB_BUILD/index.html" ]; then
36+
cp "$SRC_DEB_BUILD/index.html" "$DEB_DIR/"
37+
fi
38+
if [ -f "$SRC_DEB_BUILD/public.key" ]; then
39+
cp "$SRC_DEB_BUILD/public.key" "$DEB_DIR/"
40+
fi
41+
42+
echo "Repository structure created successfully"
43+
44+
# List the structure
45+
echo "Repository structure:"
46+
find "$DEB_DIR" -type d | sort
47+
48+
# Environment variables passed from the Node.js script
49+
if [ -n "$DEB_ASSET_NAME" ] && ([ -n "$DEB_ASSET_URL" ] || [ -n "$DEB_FILE_PATH" ]); then
50+
echo "Found amd64 .deb asset: $DEB_ASSET_NAME"
51+
52+
if [ -n "$DEB_FILE_PATH" ]; then
53+
# Use local file instead of downloading
54+
echo "Using local .deb file: $DEB_FILE_PATH"
55+
56+
if [ ! -f "$DEB_FILE_PATH" ]; then
57+
echo "Error: Local .deb file not found at $DEB_FILE_PATH"
58+
exit 1
59+
fi
60+
61+
# Copy the local file to the pool directory
62+
cp "$DEB_FILE_PATH" "$DEB_DIR/pool/main/e/electerm/$DEB_ASSET_NAME"
63+
if [ $? -eq 0 ]; then
64+
echo "Successfully copied local file: $DEB_ASSET_NAME"
65+
echo "File size: $(stat -c%s "$DEB_DIR/pool/main/e/electerm/$DEB_ASSET_NAME" 2>/dev/null || stat -f%z "$DEB_DIR/pool/main/e/electerm/$DEB_ASSET_NAME") bytes"
66+
else
67+
echo "Failed to copy local file: $DEB_FILE_PATH"
68+
exit 1
69+
fi
70+
else
71+
# Download the .deb file to the pool directory
72+
echo "Downloading: $DEB_ASSET_NAME"
73+
echo "URL: $DEB_ASSET_URL"
74+
75+
curl -L -o "$DEB_DIR/pool/main/e/electerm/$DEB_ASSET_NAME" "$DEB_ASSET_URL"
76+
if [ $? -eq 0 ]; then
77+
echo "Successfully downloaded: $DEB_ASSET_NAME"
78+
echo "File size: $(stat -c%s "$DEB_DIR/pool/main/e/electerm/$DEB_ASSET_NAME" 2>/dev/null || stat -f%z "$DEB_DIR/pool/main/e/electerm/$DEB_ASSET_NAME") bytes"
79+
else
80+
echo "Failed to download: $DEB_ASSET_NAME"
81+
exit 1
82+
fi
83+
fi
84+
85+
# Generate Packages file in the proper location
86+
echo "Generating Packages file..."
87+
PACKAGES_DIR="$DEB_DIR/dists/stable/main/binary-amd64"
88+
PACKAGES_FILE="$PACKAGES_DIR/Packages"
89+
> "$PACKAGES_FILE" # Clear the file
90+
91+
# Process .deb files from the pool
92+
for deb_file in "$DEB_DIR/pool/main/e/electerm"/*.deb; do
93+
if [ -f "$deb_file" ]; then
94+
deb_basename=$(basename "$deb_file")
95+
echo "Processing package: $deb_basename"
96+
97+
# Extract control file from the .deb package
98+
tmpdir=$(mktemp -d)
99+
dpkg-deb --control "$deb_file" "$tmpdir"
100+
101+
# Read control file and extract needed fields
102+
if [ -f "$tmpdir/control" ]; then
103+
# Extract specific fields in the correct order
104+
grep -E "^(Package|Version|Architecture|Maintainer|Description|Depends|Priority|Section):" "$tmpdir/control" >> "$PACKAGES_FILE"
105+
fi
106+
107+
# Clean up temp directory
108+
rm -rf "$tmpdir"
109+
110+
# Add file information with relative path from repository root
111+
echo "Filename: pool/main/e/electerm/$deb_basename" >> "$PACKAGES_FILE"
112+
echo "Size: $(stat -c%s "$deb_file" 2>/dev/null || stat -f%z "$deb_file")" >> "$PACKAGES_FILE"
113+
echo "MD5sum: $(md5sum "$deb_file" 2>/dev/null | cut -d' ' -f1 || md5 -q "$deb_file")" >> "$PACKAGES_FILE"
114+
echo "SHA1: $(sha1sum "$deb_file" 2>/dev/null | cut -d' ' -f1 || shasum -a 1 "$deb_file" | cut -d' ' -f1)" >> "$PACKAGES_FILE"
115+
echo "SHA256: $(sha256sum "$deb_file" 2>/dev/null | cut -d' ' -f1 || shasum -a 256 "$deb_file" | cut -d' ' -f1)" >> "$PACKAGES_FILE"
116+
echo "" >> "$PACKAGES_FILE"
117+
fi
118+
done
119+
120+
# Compress Packages file
121+
gzip -k "$PACKAGES_FILE"
122+
123+
# Generate Release file in the proper location
124+
echo "Generating Release file..."
125+
RELEASE_DIR="$DEB_DIR/dists/stable"
126+
RELEASE_FILE="$RELEASE_DIR/Release"
127+
RELEASE_DATE_FORMATTED=""
128+
if [ -n "$RELEASE_DATE" ]; then
129+
# Try to format the release date, fallback to current date
130+
RELEASE_DATE_FORMATTED=$(date -u -d "$RELEASE_DATE" '+%a, %d %b %Y %H:%M:%S UTC' 2>/dev/null || date -u '+%a, %d %b %Y %H:%M:%S UTC')
131+
else
132+
RELEASE_DATE_FORMATTED=$(date -u '+%a, %d %b %Y %H:%M:%S UTC')
133+
fi
134+
135+
cat > "$RELEASE_FILE" << EOF
136+
Origin: Electerm
137+
Label: Electerm Repository
138+
Suite: stable
139+
Codename: stable
140+
Architectures: amd64
141+
Components: main
142+
Description: Official Electerm Debian Repository
143+
Date: $RELEASE_DATE_FORMATTED
144+
EOF
145+
146+
# Add version information if available
147+
if [ -n "$RELEASE_TAG" ]; then
148+
echo "Version: $RELEASE_TAG" >> "$RELEASE_FILE"
149+
fi
150+
151+
# Add checksums to Release file (relative to dists/stable directory)
152+
cd "$RELEASE_DIR"
153+
echo "MD5Sum:" >> "$RELEASE_FILE"
154+
for file in main/binary-amd64/Packages main/binary-amd64/Packages.gz; do
155+
if [ -f "$file" ]; then
156+
md5_hash=$(md5sum "$file" 2>/dev/null | cut -d' ' -f1 || md5 -q "$file")
157+
size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file")
158+
printf " %s %8s %s\n" "$md5_hash" "$size" "$file" >> "$RELEASE_FILE"
159+
fi
160+
done
161+
162+
echo "SHA1:" >> "$RELEASE_FILE"
163+
for file in main/binary-amd64/Packages main/binary-amd64/Packages.gz; do
164+
if [ -f "$file" ]; then
165+
sha1_hash=$(sha1sum "$file" 2>/dev/null | cut -d' ' -f1 || shasum -a 1 "$file" | cut -d' ' -f1)
166+
size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file")
167+
printf " %s %8s %s\n" "$sha1_hash" "$size" "$file" >> "$RELEASE_FILE"
168+
fi
169+
done
170+
171+
echo "SHA256:" >> "$RELEASE_FILE"
172+
for file in main/binary-amd64/Packages main/binary-amd64/Packages.gz; do
173+
if [ -f "$file" ]; then
174+
sha256_hash=$(sha256sum "$file" 2>/dev/null | cut -d' ' -f1 || shasum -a 256 "$file" | cut -d' ' -f1)
175+
size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file")
176+
printf " %s %8s %s\n" "$sha256_hash" "$size" "$file" >> "$RELEASE_FILE"
177+
fi
178+
done
179+
180+
echo "Repository files generated successfully!"
181+
182+
# Delete the actual .deb file since we use URL rewrite rules in vercel.json
183+
echo "Deleting .deb file (using URL rewrite instead)..."
184+
if [ -f "$DEB_DIR/pool/main/e/electerm/$DEB_ASSET_NAME" ]; then
185+
rm "$DEB_DIR/pool/main/e/electerm/$DEB_ASSET_NAME"
186+
echo "Deleted: $DEB_ASSET_NAME"
187+
fi
188+
189+
else
190+
echo "No .deb asset to download"
191+
fi
192+
193+
# Display release information if provided
194+
if [ -n "$RELEASE_TAG" ]; then
195+
echo "Release tag: $RELEASE_TAG"
196+
fi
197+
198+
if [ -n "$RELEASE_DATE" ]; then
199+
echo "Release date: $RELEASE_DATE"
200+
fi
201+
202+
if [ -n "$GPG_KEY_ID" ]; then
203+
echo "GPG Key ID provided: $GPG_KEY_ID"
204+
205+
if [ -n "$GPG_PRIVATE_KEY" ]; then
206+
echo "GPG Private Key provided, signing repository..."
207+
208+
# Import GPG private key
209+
echo "$GPG_PRIVATE_KEY" | base64 -d | gpg --batch --import
210+
211+
# Sign the Release file in the proper location
212+
RELEASE_DIR="$DEB_DIR/dists/stable"
213+
cd "$RELEASE_DIR"
214+
if [ -f "Release" ]; then
215+
gpg --batch --yes --detach-sign --armor --local-user "$GPG_KEY_ID" --output Release.gpg Release
216+
gpg --batch --yes --clearsign --local-user "$GPG_KEY_ID" --output InRelease Release
217+
echo "Repository signed successfully!"
218+
else
219+
echo "Release file not found, skipping signing"
220+
fi
221+
else
222+
echo "GPG Private Key not provided, skipping signing"
223+
fi
224+
else
225+
echo "GPG Key ID not provided, skipping signing"
226+
fi
227+
228+
echo "Debian repository build completed successfully!"

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"b1": "node bin/build-all.js",
1313
"b2": "node bin/build-js.js",
1414
"down": "node bin/fetch-release-info.js",
15+
"deb": "node bin/build-deb.js",
1516
"sitemap": "node bin/sitemap.js",
1617
"build": "echo \"ok\"",
1718
"fix": "standard --fix",

sample.env

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@ SERVER_HOST=127.0.0.1
99
ENTRY_NAME=index
1010
ENTRY=src/views/index.js
1111
OUT=public
12-
LIB_NAME=Index
12+
LIB_NAME=Index
13+
GPG_KEY_ID=
14+
GPG_PRIVATE_KEY=
15+
DEB_FILE_PATH=

0 commit comments

Comments
 (0)