diff --git a/.github/workflows/upload.yaml b/.github/workflows/upload.yaml index eb96ac4..d3ddfa8 100644 --- a/.github/workflows/upload.yaml +++ b/.github/workflows/upload.yaml @@ -67,28 +67,23 @@ jobs: export VITE_BASE_URL="${CDN_ORIGIN}/${asset_prefix}" echo "VITE_BASE_URL=${VITE_BASE_URL}" >> "$GITHUB_ENV" echo "prefix=${asset_prefix}" >> "$GITHUB_OUTPUT" + echo "base-url=${VITE_BASE_URL}" >> "$GITHUB_OUTPUT" calcit calcit.cirru js node --test scripts/upgrade.test.mjs yarn vite build --base="$VITE_BASE_URL" - - name: Verify CDN asset references - run: node scripts/verify-cdn-build.mjs - - name: Upload static assets to COS if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository - uses: worktools/cos-upload-action@0ce57b26b03dbdd27a4a544a06d453415932c62d # v1.0.0 + uses: worktools/cos-upload-action@a8222e494b880b775cb8fe1ce9cc974d3ffc84cf # v1.1.0 with: source-dir: dist bucket: ${{ secrets.COS_BUCKET }} region: ap-shanghai prefix: ${{ steps.asset-path.outputs.prefix }} + public-base-url: ${{ steps.asset-path.outputs.base-url }} secret-id: ${{ secrets.COS_SECRET_ID }} secret-key: ${{ secrets.COS_SECRET_KEY }} - - name: Verify uploaded CDN assets - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository - run: node scripts/verify-cdn-build.mjs --remote - - name: Deploy to server id: deploy if: github.event_name == 'push' && github.ref == 'refs/heads/main' diff --git a/scripts/verify-cdn-build.mjs b/scripts/verify-cdn-build.mjs deleted file mode 100644 index 44ddf7a..0000000 --- a/scripts/verify-cdn-build.mjs +++ /dev/null @@ -1,64 +0,0 @@ -import { existsSync, readFileSync, statSync } from 'node:fs'; -import { join } from 'node:path'; - -const base = process.env.VITE_BASE_URL; - -if (!base || !base.startsWith('https://') || !base.endsWith('/')) { - throw new Error('VITE_BASE_URL must be an absolute HTTPS URL ending in /'); -} - -const html = readFileSync('dist/index.html', 'utf8'); -const assetUrls = [...html.matchAll(/(?:src|href)="(https:\/\/cos-sh\.tiye\.me\/[^\"]+)"/g)].map( - (match) => match[1], -); - -if (!assetUrls.some((url) => url.endsWith('.js'))) { - throw new Error('Built HTML must load JavaScript from COS'); -} - -const assets = assetUrls.map((url) => { - if (!url.startsWith(base)) { - throw new Error(`Asset URL is outside VITE_BASE_URL: ${url}`); - } - - const relativePath = decodeURIComponent(url.slice(base.length)); - const localPath = join('dist', relativePath); - if (!relativePath.startsWith('assets/') || !existsSync(localPath)) { - throw new Error(`Asset URL has no matching local build output: ${url}`); - } - - return { url, localPath }; -}); - -console.log(`Verified ${assets.length} local COS asset reference(s) under ${base}`); - -if (process.argv.includes('--remote')) { - for (const { url, localPath } of assets) { - let verified = false; - - for (let attempt = 0; attempt < 6; attempt += 1) { - try { - const separator = url.includes('?') ? '&' : '?'; - const response = await fetch( - `${url}${separator}run=${process.env.GITHUB_RUN_ID ?? 'local'}-${attempt}`, - { cache: 'no-store' }, - ); - const body = await response.arrayBuffer(); - if (response.ok && body.byteLength === statSync(localPath).size) { - verified = true; - break; - } - } catch { - // CDN propagation can briefly fail after the upload. - } - - await new Promise((resolve) => setTimeout(resolve, 2000)); - } - - if (!verified) { - throw new Error(`Uploaded asset was not available from the CDN: ${url}`); - } - } - - console.log(`Verified ${assets.length} uploaded asset(s) through the public CDN`); -}