CI: download previous build using GitHub Actions

This commit is contained in:
SukkaW 2025-01-18 22:57:41 +08:00
parent 5e0780af35
commit a812c40384
6 changed files with 42 additions and 69 deletions

View File

@ -30,6 +30,33 @@ jobs:
with: with:
node-version-file: ".node-version" node-version-file: ".node-version"
cache: "pnpm" cache: "pnpm"
- name: Create RAM Disk for building
id: ramdisk
run: |
BUILD_DIR=$(mktemp -d -p /dev/shm/ -t sukka-surge-public.XXXXXXXXXX)
echo "Build dir created at $BUILD_DIR"
echo "build_dir=$BUILD_DIR" >> $GITHUB_OUTPUT
- name: Download Previous Build
uses: actions/checkout@v4
with:
repository: SukkaLab/ruleset.skk.moe
persist-credentials: false
path: previous-build-${{ github.run_id }}-${{ github.run_number }}
- run: mv previous-build-${{ github.run_id }}-${{ github.run_number }}/{.,}* ${{ steps.ramdisk.outputs.build_dir }}/
- name: build folder check
# If the public directory doesn't exist, the build should fail.
# If the public directory is empty, the build should fail.
run: |
if [ ! -d ${{ steps.ramdisk.outputs.build_dir }}/.git ]; then
echo ".git not found"
exit 1
fi
if [ ! -d ${{ steps.ramdisk.outputs.build_dir }}/List ]; then
echo "List not found"
exit 1
fi
echo "public directory is ready: ${{ steps.ramdisk.outputs.build_dir }}"
- run: rm -rf "${{ steps.ramdisk.outputs.build_dir }}/.git"
- name: Get current date - name: Get current date
id: date id: date
run: | run: |
@ -57,16 +84,17 @@ jobs:
${{ runner.os }}-v3- ${{ runner.os }}-v3-
- run: pnpm install - run: pnpm install
- run: pnpm run build - run: pnpm run build
id: build env:
PUBLIC_DIR: ${{ steps.ramdisk.outputs.build_dir }}
- name: Pre-deploy check - name: Pre-deploy check
# If the public directory doesn't exist, the build should fail. # If the public directory doesn't exist, the build should fail.
# If the public directory is empty, the build should fail. # If the public directory is empty, the build should fail.
run: | run: |
if [ ! -d ${{ steps.build.outputs.public_dir }} ]; then if [ ! -d ${{ steps.ramdisk.outputs.build_dir }} ]; then
echo "public directory not found" echo "public directory not found"
exit 1 exit 1
fi fi
if [ ! "$(ls -A ${{ steps.build.outputs.public_dir }})" ]; then if [ ! "$(ls -A ${{ steps.ramdisk.outputs.build_dir }})" ]; then
echo "public directory is empty" echo "public directory is empty"
exit 1 exit 1
fi fi
@ -74,11 +102,11 @@ jobs:
echo ".BUILD_FINISHED not found" echo ".BUILD_FINISHED not found"
exit 1 exit 1
fi fi
echo "public directory is ready: ${{ steps.build.outputs.public_dir }}" echo "public directory is ready: ${{ steps.ramdisk.outputs.build_dir }}"
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v4
with: with:
name: build-artifact-${{ github. ref_name }} name: build-artifact-${{ github. ref_name }}
path: ${{ steps.build.outputs.public_dir }} path: ${{ steps.ramdisk.outputs.build_dir }}
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1
compression-level: 4 compression-level: 4

View File

@ -1,6 +1,5 @@
import path from 'node:path'; import path from 'node:path';
import fs from 'node:fs'; import process from 'node:process';
import { isCI } from 'ci-info';
export const ROOT_DIR = path.resolve(__dirname, '../..'); export const ROOT_DIR = path.resolve(__dirname, '../..');
@ -8,9 +7,7 @@ export const CACHE_DIR = path.resolve(ROOT_DIR, '.cache');
export const SOURCE_DIR = path.join(ROOT_DIR, 'Source'); export const SOURCE_DIR = path.join(ROOT_DIR, 'Source');
export const PUBLIC_DIR = isCI export const PUBLIC_DIR = process.env.PUBLIC_DIR || path.resolve(ROOT_DIR, 'public');
? fs.mkdtempSync('/dev/shm/sukkaw-surge-public-')
: path.resolve(ROOT_DIR, 'public');
export const OUTPUT_SURGE_DIR = path.join(PUBLIC_DIR, 'List'); export const OUTPUT_SURGE_DIR = path.join(PUBLIC_DIR, 'List');
export const OUTPUT_CLASH_DIR = path.resolve(PUBLIC_DIR, 'Clash'); export const OUTPUT_CLASH_DIR = path.resolve(PUBLIC_DIR, 'Clash');

View File

@ -10,6 +10,7 @@ import picocolors from 'picocolors';
import { PUBLIC_DIR } from './constants/dir'; import { PUBLIC_DIR } from './constants/dir';
import { requestWithLog } from './lib/fetch-retry'; import { requestWithLog } from './lib/fetch-retry';
import { isDirectoryEmptySync } from './lib/misc'; import { isDirectoryEmptySync } from './lib/misc';
import { isCI } from 'ci-info';
const GITHUB_CODELOAD_URL = 'https://codeload.github.com/sukkalab/ruleset.skk.moe/tar.gz/master'; const GITHUB_CODELOAD_URL = 'https://codeload.github.com/sukkalab/ruleset.skk.moe/tar.gz/master';
const GITLAB_CODELOAD_URL = 'https://gitlab.com/SukkaW/ruleset.skk.moe/-/archive/master/ruleset.skk.moe-master.tar.gz'; const GITLAB_CODELOAD_URL = 'https://gitlab.com/SukkaW/ruleset.skk.moe/-/archive/master/ruleset.skk.moe-master.tar.gz';
@ -20,6 +21,11 @@ export const downloadPreviousBuild = task(require.main === module, __filename)(a
return; return;
} }
// we uses actions/checkout to download the previous build now, so we should throw if the directory is empty
if (isCI) {
throw new Error('CI environment detected, but public directory is empty');
}
const tarGzUrl = await span.traceChildAsync('get tar.gz url', async () => { const tarGzUrl = await span.traceChildAsync('get tar.gz url', async () => {
const resp = await requestWithLog(GITHUB_CODELOAD_URL, { method: 'HEAD' }); const resp = await requestWithLog(GITHUB_CODELOAD_URL, { method: 'HEAD' });
if (resp.statusCode !== 200) { if (resp.statusCode !== 200) {

View File

@ -29,9 +29,7 @@ import { buildCloudMounterRules } from './build-cloudmounter-rules';
import { createSpan, printTraceResult, whyIsNodeRunning } from './trace'; import { createSpan, printTraceResult, whyIsNodeRunning } from './trace';
import { buildDeprecateFiles } from './build-deprecate-files'; import { buildDeprecateFiles } from './build-deprecate-files';
import path from 'node:path'; import path from 'node:path';
import { PUBLIC_DIR, ROOT_DIR } from './constants/dir'; import { ROOT_DIR } from './constants/dir';
import { setOutput } from '@actions/core';
process.on('uncaughtException', (error) => { process.on('uncaughtException', (error) => {
console.error('Uncaught exception:', error); console.error('Uncaught exception:', error);
@ -108,10 +106,6 @@ const buildFinishedLock = path.join(ROOT_DIR, '.BUILD_FINISHED');
// write a file to demonstrate that the build is finished // write a file to demonstrate that the build is finished
fs.writeFileSync(buildFinishedLock, 'BUILD_FINISHED\n'); fs.writeFileSync(buildFinishedLock, 'BUILD_FINISHED\n');
if (process.env.GITHUB_OUTPUT) {
setOutput('public_dir', PUBLIC_DIR);
}
// Finish the build to avoid leaking timer/fetch ref // Finish the build to avoid leaking timer/fetch ref
await whyIsNodeRunning(); await whyIsNodeRunning();
process.exit(0); process.exit(0);

View File

@ -20,7 +20,6 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@actions/core": "^1.11.1",
"@ghostery/adblocker": "^2.3.1", "@ghostery/adblocker": "^2.3.1",
"@henrygd/queue": "^1.0.7", "@henrygd/queue": "^1.0.7",
"async-retry": "^1.3.3", "async-retry": "^1.3.3",

51
pnpm-lock.yaml generated
View File

@ -19,9 +19,6 @@ importers:
.: .:
dependencies: dependencies:
'@actions/core':
specifier: ^1.11.1
version: 1.11.1
'@ghostery/adblocker': '@ghostery/adblocker':
specifier: ^2.3.1 specifier: ^2.3.1
version: 2.3.1 version: 2.3.1
@ -164,18 +161,6 @@ importers:
packages: packages:
'@actions/core@1.11.1':
resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==}
'@actions/exec@1.1.1':
resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==}
'@actions/http-client@2.2.3':
resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==}
'@actions/io@1.1.3':
resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==}
'@antfu/utils@0.7.10': '@antfu/utils@0.7.10':
resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==}
@ -249,10 +234,6 @@ packages:
resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==} resolution: {integrity: sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@fastify/busboy@2.1.1':
resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==}
engines: {node: '>=14'}
'@ghostery/adblocker-content@2.3.1': '@ghostery/adblocker-content@2.3.1':
resolution: {integrity: sha512-8ZTY1sEE218b0EMk3Q9fv/cWwUxunSCyBOaKuviEmJY5EyvPa1VbGPuTq/Qdvo1kduD8nLEzCwgWhcT3F3TT0Q==} resolution: {integrity: sha512-8ZTY1sEE218b0EMk3Q9fv/cWwUxunSCyBOaKuviEmJY5EyvPa1VbGPuTq/Qdvo1kduD8nLEzCwgWhcT3F3TT0Q==}
@ -1745,10 +1726,6 @@ packages:
tunnel-agent@0.6.0: tunnel-agent@0.6.0:
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
tunnel@0.0.6:
resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==}
engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'}
type-check@0.4.0: type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
@ -1773,10 +1750,6 @@ packages:
undici-types@6.20.0: undici-types@6.20.0:
resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
undici@5.28.5:
resolution: {integrity: sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==}
engines: {node: '>=14.0'}
undici@7.2.3: undici@7.2.3:
resolution: {integrity: sha512-2oSLHaDalSt2/O/wHA9M+/ZPAOcU2yrSP/cdBYJ+YxZskiPYDSqHbysLSlD7gq3JMqOoJI5O31RVU3BxX/MnAA==} resolution: {integrity: sha512-2oSLHaDalSt2/O/wHA9M+/ZPAOcU2yrSP/cdBYJ+YxZskiPYDSqHbysLSlD7gq3JMqOoJI5O31RVU3BxX/MnAA==}
engines: {node: '>=20.18.1'} engines: {node: '>=20.18.1'}
@ -1870,22 +1843,6 @@ packages:
snapshots: snapshots:
'@actions/core@1.11.1':
dependencies:
'@actions/exec': 1.1.1
'@actions/http-client': 2.2.3
'@actions/exec@1.1.1':
dependencies:
'@actions/io': 1.1.3
'@actions/http-client@2.2.3':
dependencies:
tunnel: 0.0.6
undici: 5.28.5(patch_hash=eyidnukwfhrd7exzoydz2h5cfq)
'@actions/io@1.1.3': {}
'@antfu/utils@0.7.10': {} '@antfu/utils@0.7.10': {}
'@babel/code-frame@7.26.2': '@babel/code-frame@7.26.2':
@ -1985,8 +1942,6 @@ snapshots:
'@eslint/core': 0.10.0 '@eslint/core': 0.10.0
levn: 0.4.1 levn: 0.4.1
'@fastify/busboy@2.1.1': {}
'@ghostery/adblocker-content@2.3.1': '@ghostery/adblocker-content@2.3.1':
dependencies: dependencies:
'@ghostery/adblocker-extended-selectors': 2.3.1 '@ghostery/adblocker-extended-selectors': 2.3.1
@ -3581,8 +3536,6 @@ snapshots:
dependencies: dependencies:
safe-buffer: 5.2.1 safe-buffer: 5.2.1
tunnel@0.0.6: {}
type-check@0.4.0: type-check@0.4.0:
dependencies: dependencies:
prelude-ls: 1.2.1 prelude-ls: 1.2.1
@ -3606,10 +3559,6 @@ snapshots:
undici-types@6.20.0: {} undici-types@6.20.0: {}
undici@5.28.5(patch_hash=eyidnukwfhrd7exzoydz2h5cfq):
dependencies:
'@fastify/busboy': 2.1.1
undici@7.2.3(patch_hash=eyidnukwfhrd7exzoydz2h5cfq): {} undici@7.2.3(patch_hash=eyidnukwfhrd7exzoydz2h5cfq): {}
unique-filename@4.0.0: unique-filename@4.0.0: