Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 95 additions & 47 deletions .github/workflows/upload.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,102 @@ on:
- main
pull_request: {}

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- uses: actions/setup-node@v6
with:
node-version: 24
package-manager-cache: false

- name: Enable Corepack
run: |
corepack enable
corepack prepare yarn@4.12.0 --activate
yarn --version

- uses: calcit-lang/setup-calcit@ca701be5a471759e442aa053cd100720bbe1f09f # v1.5.0

- name: "install modules"
run: caps --ci

- name: "validate snapshot and compile"
run: |
cr calcit.cirru edit format
git diff --exit-code -- calcit.cirru
cr calcit.cirru --check-only
cr calcit.cirru analyze check-types --summary-only --format json
cr calcit.cirru analyze weak-types --only schema-dynamic,code-dynamic --intent unresolved --summary-only --format json
cr calcit.cirru analyze deprecated --summary-only --format json
cr calcit.cirru js
yarn install --immutable
yarn vite build --base=./
node --test scripts/upgrade.test.mjs

- name: Deploy to server
id: deploy
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: Pendect/action-rsyncer@v2.0.0
env:
DEPLOY_KEY: ${{secrets.rsync_private_key}}
with:
flags: '-avzr --progress'
options: ''
ssh_options: ''
src: 'dist/*'
dest: 'rsync-user@tiye.me:/web-assets/repo/${{ github.repository }}'

- name: Display status from deploy
if: steps.deploy.outcome != 'skipped'
run: echo "${{ steps.deploy.outputs.status }}"
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
with:
node-version: 24
package-manager-cache: false

- uses: calcit-lang/setup-calcit@ca701be5a471759e442aa053cd100720bbe1f09f # v1.5.0
with:
tools: calcit,caps
caps-version: "0.1.1"

- name: Enable Corepack
run: |
corepack enable
corepack prepare yarn@4.18.0 --activate
yarn --version

# Current Respo modules still request preceding compatible releases, so
# strict Caps resolution rejects the highest SemVer set selected here.
- name: Install and validate dependencies
run: |
caps --ci
yarn install --immutable
caps verify --toolchain

- name: Validate Calcit snapshot
run: |
calcit calcit.cirru fix --workflow strict --verify --format edn
calcit calcit.cirru edit format
git diff --exit-code -- calcit.cirru
calcit calcit.cirru --check-only
calcit calcit.cirru analyze check-types --summary-only --format json
calcit calcit.cirru analyze weak-types --only schema-dynamic,code-dynamic --intent unresolved --summary-only --format json
calcit calcit.cirru analyze deprecated --summary-only --format json
calcit calcit.cirru analyze dynamic-methods --summary-only --format json | jq -e '.data.summary.findings == 0'

- name: Build client with CDN asset URLs
id: asset-path
env:
CDN_ORIGIN: https://cos-sh.tiye.me
run: |
if [[ "$GITHUB_EVENT_NAME" == "pull_request" ]]; then
asset_prefix="${GITHUB_REPOSITORY}/pr/"
elif [[ "$GITHUB_REF" == "refs/heads/main" ]]; then
asset_prefix="${GITHUB_REPOSITORY}/"
else
asset_prefix="${GITHUB_REPOSITORY}/branches/${GITHUB_REF_NAME}/"
fi
export VITE_BASE_URL="${CDN_ORIGIN}/${asset_prefix}"
echo "VITE_BASE_URL=${VITE_BASE_URL}" >> "$GITHUB_ENV"
echo "prefix=${asset_prefix}" >> "$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
with:
source-dir: dist
bucket: ${{ secrets.COS_BUCKET }}
region: ap-shanghai
prefix: ${{ steps.asset-path.outputs.prefix }}
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'
uses: Pendect/action-rsyncer@8e05ffa5c93e5d9c9b167796b26044d2c616b2b9 # v2.0.0
env:
DEPLOY_KEY: ${{secrets.rsync_private_key}}
with:
flags: "-avzr --progress"
options: ""
ssh_options: ""
src: "dist/*"
dest: "rsync-user@tiye.me:/web-assets/repo/${{ github.repository }}"

- name: Display status from deploy
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: echo "${{ steps.deploy.outputs.status }}"
2 changes: 2 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
nodeLinker: node-modules
npmPreapprovedPackages:
- "@calcit/procs@0.27.0"
10 changes: 5 additions & 5 deletions deps.cirru
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

{} (:calcit-version |0.22.0-alpha.3)
{} (:calcit-version |0.27.0)
:version |0.1.3
:dependencies $ {} (|Respo/reel.calcit |0.6.30)
|Respo/respo-markdown.calcit |0.4.43
|Respo/respo-ui.calcit |0.7.30
|Respo/respo.calcit |0.16.112
:dependencies $ {} (|Respo/reel.calcit |0.6.33-alpha.1)
|Respo/respo-markdown.calcit |0.4.46
|Respo/respo-ui.calcit |0.7.32-alpha.2
|Respo/respo.calcit |0.16.114-alpha.5
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
},
"author": "jiyinyiyong",
"license": "MIT",
"packageManager": "yarn@4.12.0",
"packageManager": "yarn@4.18.0",
"devDependencies": {
"bottom-tip": "^0.1.5",
"vite": "^7.3.1"
},
"dependencies": {
"@calcit/procs": "0.22.0-alpha.3",
"@calcit/procs": "0.27.0",
"diff": "^8.0.2"
}
}
64 changes: 64 additions & 0 deletions scripts/verify-cdn-build.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
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`);
}
12 changes: 6 additions & 6 deletions yarn.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading