-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathJenkinsfile
More file actions
307 lines (264 loc) · 13 KB
/
Jenkinsfile
File metadata and controls
307 lines (264 loc) · 13 KB
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
pipeline {
agent any
options {
buildDiscarder(logRotator(numToKeepStr: '20'))
}
environment {
MEDIAWIKI_VERSION = '1.43.6'
// Bump this to force rebuild of cached MediaWiki + extensions
BUILD_CACHE_VERSION = '4'
SECRETS_DIR = '/var/jenkins_home/secrets'
BUILD_DIR = "${WORKSPACE}/build"
MW_DIR = "${BUILD_DIR}/mediawiki"
}
stages {
stage('Setup Secrets') {
steps {
sh '''#!/bin/bash
# Copy LocalSettings.local.php from secrets
if [ -f "${SECRETS_DIR}/pickipedia/LocalSettings.local.php" ]; then
cp "${SECRETS_DIR}/pickipedia/LocalSettings.local.php" LocalSettings.local.php
chmod 644 LocalSettings.local.php
else
echo "ERROR: LocalSettings.local.php not found in secrets"
exit 1
fi
'''
}
}
stage('Download MediaWiki') {
steps {
sh '''#!/bin/bash
set -e
mkdir -p "${BUILD_DIR}"
MW_TARBALL="mediawiki-${MEDIAWIKI_VERSION}.tar.gz"
MW_URL="https://releases.wikimedia.org/mediawiki/${MEDIAWIKI_VERSION%.*}/mediawiki-${MEDIAWIKI_VERSION}.tar.gz"
# Check if we have cached version (includes BUILD_CACHE_VERSION to force rebuilds)
CACHE_KEY="${MEDIAWIKI_VERSION}-${BUILD_CACHE_VERSION}"
if [ -f "${BUILD_DIR}/.mw-version" ] && [ "$(cat "${BUILD_DIR}/.mw-version")" = "${CACHE_KEY}" ]; then
echo "Using cached MediaWiki ${MEDIAWIKI_VERSION} (cache v${BUILD_CACHE_VERSION})"
else
echo "Downloading MediaWiki ${MEDIAWIKI_VERSION}..."
curl -fSL "${MW_URL}" -o "${BUILD_DIR}/${MW_TARBALL}"
echo "Extracting..."
rm -rf "${MW_DIR}"
mkdir -p "${MW_DIR}"
tar -xzf "${BUILD_DIR}/${MW_TARBALL}" -C "${MW_DIR}" --strip-components=1
echo "${CACHE_KEY}" > "${BUILD_DIR}/.mw-version"
rm "${BUILD_DIR}/${MW_TARBALL}"
fi
'''
}
}
stage('Install Extensions') {
steps {
sh '''#!/bin/bash
set -e
# Copy our configuration into MediaWiki
cp LocalSettings.php "${MW_DIR}/"
cp LocalSettings.local.php "${MW_DIR}/"
cp .htaccess "${MW_DIR}/"
# Copy composer.json as composer.local.json for MediaWiki
cp composer.json "${MW_DIR}/composer.local.json"
# Install composer dependencies - only if composer.json changed
cd "${MW_DIR}"
COMPOSER_HASH=$(md5sum composer.local.json | cut -d' ' -f1)
CACHED_HASH=""
if [ -f ".composer-hash" ]; then
CACHED_HASH=$(cat .composer-hash)
fi
if [ "$COMPOSER_HASH" != "$CACHED_HASH" ] || [ ! -d "vendor" ]; then
echo "composer.json changed or vendor missing - running composer update..."
rm -f composer.lock
rm -rf vendor
# Add audit ignore for PHPUnit advisory to root composer.json
# (composer.local.json config doesn't apply to root requirements)
php -r '
$json = json_decode(file_get_contents("composer.json"), true);
$json["config"]["audit"] = ["abandoned" => "ignore", "ignore" => ["PKSA-z3gr-8qht-p93v"]];
file_put_contents("composer.json", json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
'
composer update --no-dev --optimize-autoloader --ignore-platform-reqs
echo "$COMPOSER_HASH" > .composer-hash
else
echo "composer.json unchanged - using cached vendor/"
fi
'''
}
}
stage('Install Non-Composer Extensions') {
steps {
sh '''#!/bin/bash
set -e
cd "${MW_DIR}/extensions"
# YouTube extension (not on Packagist)
if [ ! -d "YouTube" ]; then
git clone --depth 1 https://github.com/wikimedia/mediawiki-extensions-YouTube.git YouTube
fi
# MsUpload - drag-and-drop multiple file upload
if [ ! -d "MsUpload" ]; then
git clone --depth 1 https://github.com/wikimedia/mediawiki-extensions-MsUpload.git MsUpload
fi
# TimedMediaHandler - video/audio playback with FFmpeg transcoding
if [ ! -d "TimedMediaHandler" ]; then
git clone --depth 1 --branch REL1_43 https://github.com/wikimedia/mediawiki-extensions-TimedMediaHandler.git TimedMediaHandler
cd TimedMediaHandler && composer install --no-dev && cd ..
fi
# RSS - embed RSS feeds in wiki pages
if [ ! -d "RSS" ]; then
git clone --depth 1 --branch REL1_43 https://github.com/wikimedia/mediawiki-extensions-RSS.git RSS
fi
# CodeMirror - syntax highlighting in the editor
if [ ! -d "CodeMirror" ]; then
git clone --depth 1 --branch REL1_43 https://github.com/wikimedia/mediawiki-extensions-CodeMirror.git CodeMirror
fi
# Echo - notifications for talk page messages, mentions, watchlist changes
if [ ! -d "Echo" ]; then
git clone --depth 1 --branch REL1_43 https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo.git Echo
fi
# Thanks - thank editors for contributions (requires Echo)
if [ ! -d "Thanks" ]; then
git clone --depth 1 --branch REL1_43 https://gerrit.wikimedia.org/r/mediawiki/extensions/Thanks.git Thanks
fi
# UserMerge - merge and delete user accounts (for bot cleanup)
if [ ! -d "UserMerge" ]; then
git clone --depth 1 --branch REL1_43 https://gerrit.wikimedia.org/r/mediawiki/extensions/UserMerge.git UserMerge
fi
# LinkSuggest - autocomplete when typing [[ or {{ in editor
if [ ! -d "LinkSuggest" ]; then
git clone --depth 1 --branch REL1_43 https://github.com/wikimedia/mediawiki-extensions-LinkSuggest.git LinkSuggest
fi
# MediaUploader - step-by-step multi-file upload wizard
if [ ! -d "MediaUploader" ]; then
git clone --depth 1 --branch REL1_43 https://github.com/wikimedia/mediawiki-extensions-MediaUploader.git MediaUploader
cd MediaUploader && composer install --no-dev --no-interaction && cd ..
fi
'''
}
}
stage('Initialize Submodules') {
steps {
sh '''#!/bin/bash
set -e
# Initialize and update git submodules (e.g., RambutanMode extension)
if [ -f "${WORKSPACE}/.gitmodules" ]; then
echo "Initializing git submodules..."
cd "${WORKSPACE}"
git submodule update --init --recursive
else
echo "No submodules to initialize"
fi
'''
}
}
stage('Copy Custom Extensions') {
steps {
sh '''#!/bin/bash
# Copy any custom extensions we've developed
# Use rsync with --checksum to only transfer changed files
if [ -d "${WORKSPACE}/extensions" ]; then
echo "Copying custom extensions..."
rsync -a --checksum "${WORKSPACE}/extensions/" "${MW_DIR}/extensions/"
else
echo "No custom extensions directory"
fi
'''
}
}
stage('Copy Assets') {
steps {
sh '''#!/bin/bash
set -e
# Copy logo and other assets
if [ -d "${WORKSPACE}/assets" ]; then
mkdir -p "${MW_DIR}/assets"
cp -r "${WORKSPACE}/assets/"* "${MW_DIR}/assets/"
fi
# Copy diagnostic script if present (for debugging)
if [ -f "${WORKSPACE}/diag.php" ]; then
cp "${WORKSPACE}/diag.php" "${MW_DIR}/"
fi
'''
}
}
stage('Copy Chain Data') {
steps {
sh '''#!/bin/bash
set -e
CHAIN_DATA_SOURCE="/var/jenkins_home/shared/chain_data"
CHAIN_DATA_DEST="${MW_DIR}/chain-data"
if [ -d "${CHAIN_DATA_SOURCE}" ] && [ -f "${CHAIN_DATA_SOURCE}/chainData.json" ]; then
echo "Copying chain data from ${CHAIN_DATA_SOURCE}..."
mkdir -p "${CHAIN_DATA_DEST}"
cp "${CHAIN_DATA_SOURCE}/chainData.json" "${CHAIN_DATA_DEST}/"
echo "Chain data copied successfully"
else
echo "Warning: Chain data not found at ${CHAIN_DATA_SOURCE}"
echo "Blue Railroad token data will not be available"
fi
'''
}
}
stage('Generate Build Info') {
steps {
sh '''#!/bin/bash
set -e
# Fetch current Ethereum mainnet block height from Blockscout
echo "Fetching current Ethereum block height..."
BLOCK_HEIGHT=$(curl -s "https://eth.blockscout.com/api/v2/blocks?type=block" | grep -o '"height":[0-9]*' | head -1 | cut -d: -f2)
if [ -n "$BLOCK_HEIGHT" ] && [ "$BLOCK_HEIGHT" -gt 0 ] 2>/dev/null; then
echo "Current block height: ${BLOCK_HEIGHT}"
else
echo "Warning: Could not fetch block height, using 0"
BLOCK_HEIGHT=0
fi
# Generate build-info.php
cat > "${MW_DIR}/build-info.php" << 'PHPEOF'
<?php
// Auto-generated at build time - do not edit
$wgPickipediaBuildInfo = [
'blockheight' => BLOCK_HEIGHT_PLACEHOLDER,
'build_number' => 'BUILD_NUMBER_PLACEHOLDER',
'commit' => 'COMMIT_PLACEHOLDER',
'build_time' => 'BUILD_TIME_PLACEHOLDER',
];
PHPEOF
# Replace placeholders with actual values
sed -i "s/BLOCK_HEIGHT_PLACEHOLDER/${BLOCK_HEIGHT}/" "${MW_DIR}/build-info.php"
sed -i "s/BUILD_NUMBER_PLACEHOLDER/${BUILD_NUMBER}/" "${MW_DIR}/build-info.php"
sed -i "s/COMMIT_PLACEHOLDER/$(git rev-parse --short HEAD)/" "${MW_DIR}/build-info.php"
sed -i "s/BUILD_TIME_PLACEHOLDER/$(date -Iseconds)/" "${MW_DIR}/build-info.php"
echo "Generated build-info.php with block ${BLOCK_HEIGHT}"
'''
}
}
stage('Stage for Deploy') {
// Note: This job only builds production branch (configured in job definition)
// so no branch conditional needed
steps {
sh '''#!/bin/bash
set -e
STAGE_DIR="/var/jenkins_home/pickipedia_stage"
MARKER_FILE="${STAGE_DIR}/.deploy-ready"
echo "Staging build to ${STAGE_DIR}..."
mkdir -p "${STAGE_DIR}"
# Rsync the built MediaWiki to staging
rsync -av --delete "${MW_DIR}/" "${STAGE_DIR}/"
# Create deploy marker
COMMIT_SHA=$(git rev-parse HEAD)
echo "commit=${COMMIT_SHA} build=${BUILD_NUMBER} time=$(date -Iseconds)" > "${MARKER_FILE}"
echo "Build staged - deploy marker created"
'''
}
}
}
post {
success {
echo "Build ${BUILD_NUMBER} succeeded"
echo "MediaWiki ${MEDIAWIKI_VERSION} built at ${MW_DIR}"
}
failure {
echo "Build ${BUILD_NUMBER} failed"
}
}
}