diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index b737757..c048e18 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -8,7 +8,7 @@ on: jobs: pages: runs-on: ubuntu-latest - container: alpine:latest + container: node:lts-alpine steps: - uses: actions/checkout@v2 - name: Install Dependencies diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3b7bcdf..72acee9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: alpine:latest +image: node:lts-alpine include: - template: Security/Secret-Detection.gitlab-ci.yml diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..b6a7d89 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +16 diff --git a/package.json b/package.json new file mode 100644 index 0000000..5bafe7c --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "botnet-filter", + "private": true, + "scripts": { + "build": "node src/build.js" + }, + "dependencies": { + "extract-zip": "^2.0.1", + "got": "^11.8.3" + }, + "engines": { + "node": ">= 14.15.0" + } +} diff --git a/src/build.js b/src/build.js new file mode 100644 index 0000000..97192ef --- /dev/null +++ b/src/build.js @@ -0,0 +1,73 @@ +'use strict' + +// for deployment outside of GitLab CI, e.g. Cloudflare Pages and Netlify + +const { stream: gotStream } = require('got') +const got = require('got') +const unzip = require('extract-zip') +const { join } = require('path') +const { mkdir } = require('fs/promises') +const { createWriteStream } = require('fs') +const { pipeline } = require('stream/promises') + +const rootPath = join(__dirname, '..') +const tmpPath = join(rootPath, 'tmp') +const publicPath = join(rootPath, 'public') +const zipPath = join(tmpPath, 'artifacts.zip') +const artifactsUrl = 'https://gitlab.com/malware-filter/botnet-filter/-/jobs/artifacts/main/download?job=pages' +const pipelineUrl = 'https://gitlab.com/malware-filter/botnet-filter/badges/main/pipeline.svg' +const ghMirror = 'https://nightly.link/curbengh/botnet-filter/workflows/pages/main/public.zip' + +const pipelineStatus = async (url) => { + try { + const svg = await got(url).text() + if (!svg.includes('passed')) throw new Error('last gitlab pipeline failed') + } catch ({ message }) { + throw new Error(message) + } +} + +const f = async () => { + let isMirror = false + + await mkdir(tmpPath, { recursive: true }) + + console.log(`Downloading artifacts.zip from "${artifactsUrl}"`) + try { + await pipeline( + gotStream(artifactsUrl), + createWriteStream(zipPath) + ) + await pipelineStatus(pipelineUrl) + } catch ({ message }) { + console.error(JSON.stringify({ + error: message, + link: artifactsUrl + })) + + console.log(`Downloading artifacts.zip from "${ghMirror}"`) + isMirror = true + + try { + await pipeline( + gotStream(ghMirror), + createWriteStream(zipPath) + ) + } catch ({ message }) { + throw new Error(JSON.stringify({ + error: message, + link: ghMirror + })) + } + } + + console.log('Extracting artifacts.zip...') + if (isMirror === false) { + await unzip(zipPath, { dir: rootPath }) + } else { + await mkdir(publicPath, { recursive: true }) + await unzip(zipPath, { dir: publicPath }) + } +} + +f()