snapshot of https://github.com/toeverything/AFFiNE.git (canary, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Build & Test / Analyze (javascript, affine) (push) Failing after 4s
Build & Test / Analyze (typescript, affine) (push) Failing after 3s
Build & Test / Rust test filter (push) Failing after 4s
Build & Test / Check yarn binary (push) Failing after 3s
Build & Test / E2E BlockSuite Test (3) (push) Failing after 3s
Build & Test / Analyze (javascript, blocksuite) (push) Failing after 3s
Build & Test / Analyze (typescript, blocksuite) (push) Failing after 3s
Build & Test / Mobile native build filter (push) Failing after 3s
Build & Test / E2E BlockSuite Test (1) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (2) (push) Failing after 4s
Build & Test / E2E Mobile Test (1) (push) Failing after 3s
Build & Test / Unit Test (1) (push) Has been skipped
Build & Test / Unit Test (2) (push) Has been skipped
Build & Test / Unit Test (3) (push) Has been skipped
Build & Test / Unit Test (4) (push) Has been skipped
Build & Test / Unit Test (5) (push) Has been skipped
Build & Test / Native Unit Test (push) Has been skipped
Build & Test / E2E BlockSuite Test (4) (push) Failing after 3s
Build & Test / E2E BlockSuite Test (5) (push) Failing after 3s
Build & Test / E2E BlockSuite Cross Browser Test (push) Failing after 3s
Build & Test / E2E Mobile Test (2) (push) Failing after 3s
Build & Test / Build AFFiNE native (x86_64-unknown-linux-gnu) (push) Failing after 3s
Build & Test / Build Server native (push) Failing after 3s
Build & Test / Check Git Status (push) Has been skipped
Build & Test / Server Test (0, 4) (push) Has been skipped
Build & Test / Server Test (1, 4) (push) Has been skipped
Build & Test / Server Test (2, 4) (push) Has been skipped
Build & Test / Server Test (3, 4) (push) Has been skipped
Build & Test / Server Test with Elasticsearch (push) Has been skipped
Build & Test / Build @affine/electron renderer (push) Failing after 3s
Build & Test / Copilot test filter (push) Failing after 4s
Build & Test / Lint Rust (push) Has been skipped
Build & Test / Server Test with Embedded Search (push) Has been skipped
Build & Test / Server Test with Manticore Search (push) Has been skipped
Build & Test / Server E2E Test (push) Has been skipped
Build & Test / Cloud Desktop E2E Test (push) Has been skipped
Build & Test / Cloud E2E Test 1/2 (push) Has been skipped
Build & Test / Cloud E2E Test 2/2 (push) Has been skipped
Build & Test / Build Android app (push) Has been skipped
Build & Test / Test Android app (push) Has been skipped
Build & Test / Run native tests (push) Has been skipped
Build & Test / Server Copilot Api Test (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (1, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (2, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (3, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (4, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (5, 5) (push) Has been skipped
Release / Canary Gate (push) Has been skipped
Build & Test / Build AFFiNE native (aarch64-apple-darwin) (push) Has been cancelled
Build & Test / Lint (push) Has been cancelled
Build & Test / Typecheck (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-apple-darwin) (push) Has been cancelled
Build & Test / Desktop Test (ubuntu-latest, linux, x64, x86_64-unknown-linux-gnu, true) (push) Has been cancelled
Build & Test / Desktop Test (windows-latest, windows, x64, x86_64-pc-windows-msvc, true) (push) Has been cancelled
Build & Test / E2E Test (1) (push) Has been cancelled
Build & Test / E2E Test (2) (push) Has been cancelled
Build & Test / E2E Test (3) (push) Has been cancelled
Build & Test / E2E Test (4) (push) Has been cancelled
Build & Test / E2E Test (5) (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, arm64, aarch64-apple-darwin, true) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, x64, x86_64-apple-darwin, false) (push) Has been cancelled
Build & Test / 3, 2, 1 Launch (push) Has been cancelled
Build & Test / Build iOS app (push) Has been cancelled
Copilot Test Automatically / Setup Test (push) Failing after 2s
Release / Prepare (push) Failing after 1s
Release / Release Mobile (push) Has been skipped
Release / Release Desktop (push) Has been skipped
Release / Release Docker Image (push) Has been skipped
Release / Release Cloud (push) Has been skipped
Some checks failed
Build & Test / Analyze (javascript, affine) (push) Failing after 4s
Build & Test / Analyze (typescript, affine) (push) Failing after 3s
Build & Test / Rust test filter (push) Failing after 4s
Build & Test / Check yarn binary (push) Failing after 3s
Build & Test / E2E BlockSuite Test (3) (push) Failing after 3s
Build & Test / Analyze (javascript, blocksuite) (push) Failing after 3s
Build & Test / Analyze (typescript, blocksuite) (push) Failing after 3s
Build & Test / Mobile native build filter (push) Failing after 3s
Build & Test / E2E BlockSuite Test (1) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (2) (push) Failing after 4s
Build & Test / E2E Mobile Test (1) (push) Failing after 3s
Build & Test / Unit Test (1) (push) Has been skipped
Build & Test / Unit Test (2) (push) Has been skipped
Build & Test / Unit Test (3) (push) Has been skipped
Build & Test / Unit Test (4) (push) Has been skipped
Build & Test / Unit Test (5) (push) Has been skipped
Build & Test / Native Unit Test (push) Has been skipped
Build & Test / E2E BlockSuite Test (4) (push) Failing after 3s
Build & Test / E2E BlockSuite Test (5) (push) Failing after 3s
Build & Test / E2E BlockSuite Cross Browser Test (push) Failing after 3s
Build & Test / E2E Mobile Test (2) (push) Failing after 3s
Build & Test / Build AFFiNE native (x86_64-unknown-linux-gnu) (push) Failing after 3s
Build & Test / Build Server native (push) Failing after 3s
Build & Test / Check Git Status (push) Has been skipped
Build & Test / Server Test (0, 4) (push) Has been skipped
Build & Test / Server Test (1, 4) (push) Has been skipped
Build & Test / Server Test (2, 4) (push) Has been skipped
Build & Test / Server Test (3, 4) (push) Has been skipped
Build & Test / Server Test with Elasticsearch (push) Has been skipped
Build & Test / Build @affine/electron renderer (push) Failing after 3s
Build & Test / Copilot test filter (push) Failing after 4s
Build & Test / Lint Rust (push) Has been skipped
Build & Test / Server Test with Embedded Search (push) Has been skipped
Build & Test / Server Test with Manticore Search (push) Has been skipped
Build & Test / Server E2E Test (push) Has been skipped
Build & Test / Cloud Desktop E2E Test (push) Has been skipped
Build & Test / Cloud E2E Test 1/2 (push) Has been skipped
Build & Test / Cloud E2E Test 2/2 (push) Has been skipped
Build & Test / Build Android app (push) Has been skipped
Build & Test / Test Android app (push) Has been skipped
Build & Test / Run native tests (push) Has been skipped
Build & Test / Server Copilot Api Test (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (1, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (2, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (3, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (4, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (5, 5) (push) Has been skipped
Release / Canary Gate (push) Has been skipped
Build & Test / Build AFFiNE native (aarch64-apple-darwin) (push) Has been cancelled
Build & Test / Lint (push) Has been cancelled
Build & Test / Typecheck (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-apple-darwin) (push) Has been cancelled
Build & Test / Desktop Test (ubuntu-latest, linux, x64, x86_64-unknown-linux-gnu, true) (push) Has been cancelled
Build & Test / Desktop Test (windows-latest, windows, x64, x86_64-pc-windows-msvc, true) (push) Has been cancelled
Build & Test / E2E Test (1) (push) Has been cancelled
Build & Test / E2E Test (2) (push) Has been cancelled
Build & Test / E2E Test (3) (push) Has been cancelled
Build & Test / E2E Test (4) (push) Has been cancelled
Build & Test / E2E Test (5) (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, arm64, aarch64-apple-darwin, true) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, x64, x86_64-apple-darwin, false) (push) Has been cancelled
Build & Test / 3, 2, 1 Launch (push) Has been cancelled
Build & Test / Build iOS app (push) Has been cancelled
Copilot Test Automatically / Setup Test (push) Failing after 2s
Release / Prepare (push) Failing after 1s
Release / Release Mobile (push) Has been skipped
Release / Release Desktop (push) Has been skipped
Release / Release Docker Image (push) Has been skipped
Release / Release Cloud (push) Has been skipped
This commit is contained in:
39
scripts/check-windows-signer.mjs
Normal file
39
scripts/check-windows-signer.mjs
Normal file
@@ -0,0 +1,39 @@
|
||||
import fs from 'node:fs';
|
||||
|
||||
const buildType = process.env.BUILD_TYPE;
|
||||
const requireSigner =
|
||||
process.env.REQUIRE_SIGNER === 'true' ||
|
||||
['beta', 'stable'].includes(buildType);
|
||||
const outputPath = process.env.GITHUB_OUTPUT;
|
||||
|
||||
const missing = [
|
||||
'AFFINE_SIGN_CLIENT_HASH',
|
||||
'AFFINE_SIGNER_ADDR',
|
||||
'AFFINE_SIGNER_TOKEN',
|
||||
'AFFINE_SIGNER_TS_AUTH_KEY',
|
||||
'WINDOWS_SIGNER_PUBLIC_CERT_BASE64',
|
||||
].filter(name => !process.env[name]);
|
||||
|
||||
if (missing.length === 0) {
|
||||
setOutput('signer_available', 'true');
|
||||
} else {
|
||||
setOutput('signer_available', 'false');
|
||||
const message = `Missing remote Windows signer configuration: ${missing.join(', ')}.`;
|
||||
if (requireSigner) {
|
||||
fail(message);
|
||||
} else {
|
||||
console.warn(
|
||||
`::warning::${message} Windows installer executables will be skipped.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function setOutput(name, value) {
|
||||
if (!outputPath) return;
|
||||
fs.appendFileSync(outputPath, `${name}=${value}\n`);
|
||||
}
|
||||
|
||||
function fail(message) {
|
||||
console.error(`::error::${message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
219
scripts/cleanup-canary-releases.sh
Executable file
219
scripts/cleanup-canary-releases.sh
Executable file
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
Clean up canary GitHub Releases (optionally their tags) in a repo.
|
||||
|
||||
Requires: gh (GitHub CLI) authenticated with access to the repo.
|
||||
|
||||
Usage:
|
||||
scripts/cleanup-canary-releases.sh [--repo OWNER/REPO] [--keep N] [--limit N]
|
||||
[--pattern REGEX] [--dedupe-by-commit]
|
||||
[--no-cleanup-tag] [--yes]
|
||||
|
||||
Options:
|
||||
--repo OWNER/REPO Target repo (default: derived from git remote origin)
|
||||
--keep N Keep the newest N canary releases (default: 30; applied after --dedupe-by-commit)
|
||||
--limit N Max releases to fetch from GitHub (default: 500)
|
||||
--pattern REGEX Regex matched against tagName (default: "-canary\.?")
|
||||
--dedupe-by-commit For the same commit, keep only the newest canary release (deletes older duplicates)
|
||||
--no-cleanup-tag Delete releases but keep remote tags (default deletes both)
|
||||
--yes Actually delete (default: dry-run)
|
||||
|
||||
Examples:
|
||||
scripts/cleanup-canary-releases.sh --keep 14
|
||||
scripts/cleanup-canary-releases.sh --dedupe-by-commit --keep 30
|
||||
scripts/cleanup-canary-releases.sh --keep 0 --limit 2000 --yes
|
||||
scripts/cleanup-canary-releases.sh --repo toeverything/AFFiNE --keep 30 --yes
|
||||
USAGE
|
||||
}
|
||||
|
||||
REPO=""
|
||||
KEEP=30
|
||||
LIMIT=500
|
||||
PATTERN='-canary\.?'
|
||||
CLEANUP_TAG=1
|
||||
DEDUPE_BY_COMMIT=0
|
||||
YES=0
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--repo)
|
||||
REPO="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--keep)
|
||||
KEEP="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--limit)
|
||||
LIMIT="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--pattern)
|
||||
PATTERN="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--dedupe-by-commit)
|
||||
DEDUPE_BY_COMMIT=1
|
||||
shift 1
|
||||
;;
|
||||
--no-cleanup-tag)
|
||||
CLEANUP_TAG=0
|
||||
shift 1
|
||||
;;
|
||||
--yes)
|
||||
YES=1
|
||||
shift 1
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown arg: $1" >&2
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ! command -v gh >/dev/null 2>&1; then
|
||||
echo "Error: gh not found in PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v node >/dev/null 2>&1; then
|
||||
echo "Error: node not found in PATH (used for safe regex quoting)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$KEEP" =~ ^[0-9]+$ ]]; then
|
||||
echo "Error: --keep must be a non-negative integer" >&2
|
||||
exit 2
|
||||
fi
|
||||
if ! [[ "$LIMIT" =~ ^[0-9]+$ ]] || [[ "$LIMIT" -lt 1 ]]; then
|
||||
echo "Error: --limit must be a positive integer" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ -z "$REPO" ]]; then
|
||||
origin="$(git config --get remote.origin.url || true)"
|
||||
if [[ -z "$origin" ]]; then
|
||||
echo "Error: cannot derive --repo (no git remote.origin.url). Pass --repo OWNER/REPO." >&2
|
||||
exit 2
|
||||
fi
|
||||
origin="${origin%.git}"
|
||||
if [[ "$origin" =~ ^git@([^:]+):(.+)$ ]]; then
|
||||
host="${BASH_REMATCH[1]}"
|
||||
path="${BASH_REMATCH[2]}"
|
||||
REPO="${host}/${path}"
|
||||
elif [[ "$origin" =~ ^https?://([^/]+)/(.+)$ ]]; then
|
||||
host="${BASH_REMATCH[1]}"
|
||||
path="${BASH_REMATCH[2]}"
|
||||
REPO="${host}/${path}"
|
||||
else
|
||||
echo "Error: unsupported origin url: $origin" >&2
|
||||
exit 2
|
||||
fi
|
||||
if [[ "$REPO" == github.com/* ]]; then
|
||||
REPO="${REPO#github.com/}"
|
||||
fi
|
||||
fi
|
||||
|
||||
pattern_json="$(node -e 'console.log(JSON.stringify(process.argv[1] ?? ""))' -- "$PATTERN")"
|
||||
|
||||
tmp_all="$(mktemp -t canary_release_tags_all.XXXXXX)"
|
||||
tmp_pairs="$(mktemp -t canary_release_tag_sha_pairs.XXXXXX)"
|
||||
tmp_keep="$(mktemp -t canary_release_tags_keep.XXXXXX)"
|
||||
tmp_dupes="$(mktemp -t canary_release_tags_dupes.XXXXXX)"
|
||||
tmp_delete="$(mktemp -t canary_release_tags_to_delete.XXXXXX)"
|
||||
trap 'rm -f "$tmp_all" "$tmp_pairs" "$tmp_keep" "$tmp_dupes" "$tmp_delete"' EXIT
|
||||
|
||||
gh release list \
|
||||
-R "$REPO" \
|
||||
-L "$LIMIT" \
|
||||
--json tagName \
|
||||
--jq ".[] | select(.tagName | test(${pattern_json})) | .tagName" >"$tmp_all"
|
||||
|
||||
total="$(wc -l <"$tmp_all" | tr -d ' ')"
|
||||
if [[ "$total" -eq 0 ]]; then
|
||||
echo "No releases matched pattern '$PATTERN' in $REPO."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$total" -le "$KEEP" ]] && [[ "$DEDUPE_BY_COMMIT" -ne 1 ]]; then
|
||||
echo "Found $total matching releases in $REPO; keep=$KEEP => nothing to delete."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$DEDUPE_BY_COMMIT" -eq 1 ]]; then
|
||||
while IFS= read -r tag; do
|
||||
[[ -n "$tag" ]] || continue
|
||||
sha="$(
|
||||
gh api "repos/$REPO/commits/$tag" --jq '.sha' 2>/dev/null || true
|
||||
)"
|
||||
if [[ -z "$sha" ]]; then
|
||||
echo "Warning: failed to resolve commit for tag $tag; keeping it to be safe." >&2
|
||||
sha="UNKNOWN:$tag"
|
||||
fi
|
||||
printf '%s\t%s\n' "$tag" "$sha" >>"$tmp_pairs"
|
||||
done <"$tmp_all"
|
||||
|
||||
awk -F'\t' -v keep_n="$KEEP" -v keep_file="$tmp_keep" -v dupes_file="$tmp_dupes" -v delete_file="$tmp_delete" '
|
||||
{
|
||||
tag=$1; sha=$2
|
||||
if (!(sha in seen)) {
|
||||
seen[sha]=1
|
||||
uniq++
|
||||
if (uniq <= keep_n) print tag >> keep_file
|
||||
else print tag >> delete_file
|
||||
} else {
|
||||
print tag >> dupes_file
|
||||
print tag >> delete_file
|
||||
}
|
||||
}
|
||||
' "$tmp_pairs"
|
||||
else
|
||||
awk -v keep_n="$KEEP" -v keep_file="$tmp_keep" -v delete_file="$tmp_delete" '
|
||||
NR <= keep_n { print >> keep_file; next }
|
||||
{ print >> delete_file }
|
||||
' "$tmp_all"
|
||||
: >"$tmp_dupes"
|
||||
fi
|
||||
|
||||
delete_count="$(wc -l <"$tmp_delete" | tr -d ' ')"
|
||||
echo "Repo: $REPO"
|
||||
echo "Pattern: $PATTERN"
|
||||
echo "Matched canary releases: $total"
|
||||
echo "Keeping newest: $KEEP"
|
||||
if [[ "$DEDUPE_BY_COMMIT" -eq 1 ]]; then
|
||||
dupes_count="$(wc -l <"$tmp_dupes" | tr -d ' ')"
|
||||
echo "Deduped by commit: yes (duplicate releases to remove: $dupes_count)"
|
||||
fi
|
||||
echo "Will delete: $delete_count"
|
||||
if [[ "$delete_count" -eq 0 ]]; then
|
||||
echo "Nothing to delete."
|
||||
exit 0
|
||||
fi
|
||||
echo
|
||||
echo "Tags to delete (newest to oldest):"
|
||||
cat "$tmp_delete"
|
||||
echo
|
||||
|
||||
if [[ "$YES" -ne 1 ]]; then
|
||||
echo "Dry-run only. Re-run with --yes to actually delete."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
while IFS= read -r tag; do
|
||||
[[ -n "$tag" ]] || continue
|
||||
echo "Deleting release: $tag"
|
||||
if [[ "$CLEANUP_TAG" -eq 1 ]]; then
|
||||
gh release delete "$tag" -R "$REPO" --yes --cleanup-tag
|
||||
else
|
||||
gh release delete "$tag" -R "$REPO" --yes
|
||||
fi
|
||||
done <"$tmp_delete"
|
||||
|
||||
echo "Done."
|
||||
28
scripts/download-blocksuite-fonts.mjs
Normal file
28
scripts/download-blocksuite-fonts.mjs
Normal file
@@ -0,0 +1,28 @@
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { AffineCanvasTextFonts } from '@blocksuite/affine/shared/services';
|
||||
|
||||
const fontPath = join(
|
||||
fileURLToPath(import.meta.url),
|
||||
'..',
|
||||
'..',
|
||||
'packages',
|
||||
'frontend',
|
||||
'core',
|
||||
'public',
|
||||
'fonts'
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
AffineCanvasTextFonts.map(async ({ url }) => {
|
||||
const buffer = await fetch(url).then(res =>
|
||||
res.arrayBuffer().then(res => Buffer.from(res))
|
||||
);
|
||||
const filename = url.split('/').pop();
|
||||
const distPath = join(fontPath, filename);
|
||||
await writeFile(distPath, buffer);
|
||||
console.info(`Downloaded ${distPath} successfully`);
|
||||
})
|
||||
);
|
||||
77
scripts/generate-release-yml.mjs
Normal file
77
scripts/generate-release-yml.mjs
Normal file
@@ -0,0 +1,77 @@
|
||||
import crypto from 'node:crypto';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
const releaseDir = path.join(process.cwd(), './release');
|
||||
|
||||
const filenamesMapping = {
|
||||
all: 'latest.yml',
|
||||
macos: 'latest-mac.yml',
|
||||
linux: 'latest-linux.yml',
|
||||
};
|
||||
|
||||
const releaseFiles = ['zip', 'exe', 'dmg', 'appimage', 'deb', 'flatpak'];
|
||||
|
||||
const generateYml = platform => {
|
||||
const yml = {
|
||||
version: process.env.RELEASE_VERSION ?? '0.0.0',
|
||||
files: [],
|
||||
};
|
||||
|
||||
const regex =
|
||||
// we involves all distribution files in one release file to enforce we handle auto updater correctly
|
||||
platform === 'all'
|
||||
? new RegExp(`.(${releaseFiles.join('|')})$`)
|
||||
: new RegExp(`.+-${platform}-.+.(${releaseFiles.join('|')})$`);
|
||||
|
||||
const files = fs.readdirSync(releaseDir).filter(file => regex.test(file));
|
||||
const outputFileName = filenamesMapping[platform];
|
||||
|
||||
console.info(`Release content for ${platform}:`);
|
||||
console.info(JSON.stringify(files, null, 2), '\n');
|
||||
|
||||
files.forEach(fileName => {
|
||||
const filePath = path.join(releaseDir, fileName);
|
||||
try {
|
||||
const fileData = fs.readFileSync(filePath);
|
||||
const hash = crypto
|
||||
.createHash('sha512')
|
||||
.update(fileData)
|
||||
.digest('base64');
|
||||
const size = fs.statSync(filePath).size;
|
||||
|
||||
yml.files.push({
|
||||
url: fileName,
|
||||
sha512: hash,
|
||||
size: size,
|
||||
});
|
||||
} catch {}
|
||||
});
|
||||
yml.releaseDate = new Date().toISOString();
|
||||
|
||||
// NOTE(@forehalo): make sure old windows x64 won't fetch windows arm64 by default
|
||||
// maybe we need to separate arm64 builds to separated yml file `latest-arm64.yml`, `latest-linux-arm64.yml`
|
||||
// check https://github.com/electron-userland/electron-builder/blob/master/packages/electron-updater/src/providers/Provider.ts#L30
|
||||
// and packages/frontend/apps/electron/src/main/updater/affine-update-provider.ts#L100
|
||||
yml.files.sort(a => (a.url.includes('windows-arm64') ? 1 : -1));
|
||||
|
||||
const ymlStr =
|
||||
`version: ${yml.version}\n` +
|
||||
`files:\n` +
|
||||
yml.files
|
||||
.map(file => {
|
||||
return (
|
||||
` - url: ${file.url}\n` +
|
||||
` sha512: ${file.sha512}\n` +
|
||||
` size: ${file.size}\n`
|
||||
);
|
||||
})
|
||||
.join('') +
|
||||
`releaseDate: ${yml.releaseDate}\n`;
|
||||
|
||||
fs.writeFileSync(path.join(releaseDir, outputFileName), ymlStr);
|
||||
};
|
||||
|
||||
generateYml('macos');
|
||||
generateYml('linux');
|
||||
generateYml('all');
|
||||
153
scripts/set-version.sh
Executable file
153
scripts/set-version.sh
Executable file
@@ -0,0 +1,153 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
for DIR_ITEM in $(yarn workspaces list --json | jq -r '.location'); do
|
||||
DIR=$(echo -n "$DIR_ITEM" | tr -d '\r\n')
|
||||
if [ -f "$DIR/package.json" ]; then
|
||||
echo "Setting version for $DIR"
|
||||
jq ".version = \"$1\"" "$DIR"/package.json > tmp.json && mv tmp.json "$DIR"/package.json
|
||||
else
|
||||
echo "No package.json found in: $DIR"
|
||||
fi
|
||||
done
|
||||
|
||||
update_app_version_in_helm_charts() {
|
||||
local file_path=$1
|
||||
local new_version=$2
|
||||
|
||||
# Check if file exists
|
||||
if [ ! -f "$file_path" ]; then
|
||||
echo "Error: File does not exist at $file_path."
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Updating $file_path with appVersion $new_version"
|
||||
|
||||
# Use sed to replace the appVersion value with the new version.
|
||||
sed -i.bak -E "s/^appVersion:[[:space:]]+[\"']?.*[\"']?$/appVersion: \"$new_version\"/" "$file_path" || {
|
||||
# If the sed command fails, print an error message and exit with a non-zero status
|
||||
echo "Error: Failed to update the appVersion in $file_path."
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "appVersion in $file_path updated to $new_version"
|
||||
|
||||
rm "$file_path".bak
|
||||
}
|
||||
|
||||
update_app_stream_version() {
|
||||
local file_path=$1
|
||||
local new_version=$2
|
||||
|
||||
# Check if file exists
|
||||
if [ ! -f "$file_path" ]; then
|
||||
echo "Error: File does not exist at $file_path."
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Updating $file_path with appVersion $new_version"
|
||||
# version is at
|
||||
# <releases>
|
||||
# <release version="0.21.0" date="yyyy-MM-dd">
|
||||
# <url>https://github.com/toeverything/AFFiNE/releases/tag/v0.21.0</url>
|
||||
# </release>
|
||||
# </releases>
|
||||
# We need to update the version and the url
|
||||
current_date=$(date +"%Y-%m-%d")
|
||||
|
||||
# Use sed to update the version, date, and URL in the releases section
|
||||
sed -i.bak -E "s|<release version=\"[^\"]*\" date=\"[^\"]*\">|<release version=\"$new_version\" date=\"$current_date\">|" "$file_path" &&
|
||||
sed -i.bak -E "s|<url>https://github.com/toeverything/AFFiNE/releases/tag/v[^<]*</url>|<url>https://github.com/toeverything/AFFiNE/releases/tag/v$new_version</url>|" "$file_path" || {
|
||||
# If the sed command fails, print an error message and exit with a non-zero status
|
||||
echo "Error: Failed to update the appVersion."
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "appVersion in $file_path updated to $new_version"
|
||||
|
||||
rm "$file_path".bak
|
||||
}
|
||||
|
||||
update_ios_marketing_version() {
|
||||
local file_path=$1
|
||||
# Normalize inputs like "v0.26.4-beta.1" to "0.26.4"
|
||||
local new_version=$(echo "$2" | sed -E 's/^v//; s/-.*$//')
|
||||
|
||||
# Check if file exists
|
||||
if [ ! -f "$file_path" ]; then
|
||||
echo "Error: File does not exist at $file_path."
|
||||
return 1
|
||||
fi
|
||||
|
||||
echo "Updating $file_path with MARKETING_VERSION $new_version"
|
||||
|
||||
# Use sed to replace the MARKETING_VERSION value with the new version
|
||||
sed -i.bak -E "s/MARKETING_VERSION = [^;]*;/MARKETING_VERSION = $new_version;/g" "$file_path" || {
|
||||
# If the sed command fails, print an error message and exit with a non-zero status
|
||||
echo "Error: Failed to update the MARKETING_VERSION."
|
||||
return 1
|
||||
}
|
||||
|
||||
echo "MARKETING_VERSION in $file_path updated to $new_version"
|
||||
|
||||
rm "$file_path".bak
|
||||
}
|
||||
|
||||
# Derive a date-based iOS MARKETING_VERSION from the latest stable/beta tag.
|
||||
# Apple requires CFBundleShortVersionString to increase monotonically. Using
|
||||
# date-based versions (YYYY.M.D) derived from the last stable/beta release tag
|
||||
# ensures this. The user-facing App Store version is set separately in
|
||||
# App Store Connect.
|
||||
get_ios_version_from_git() {
|
||||
# Find the most recent stable/beta tag reachable from HEAD (exclude canary/nightly)
|
||||
local latest_tag
|
||||
latest_tag=$(git describe --tags --match 'v[0-9]*' \
|
||||
--exclude '*canary*' --exclude '*nightly*' \
|
||||
--abbrev=0 HEAD 2>/dev/null)
|
||||
|
||||
if [ -z "$latest_tag" ]; then
|
||||
# No stable/beta tag found, fall back to today's date
|
||||
date +"%Y.%-m.%-d"
|
||||
return
|
||||
fi
|
||||
|
||||
# Get the tag creation date (tagger date for annotated tags, commit date for lightweight)
|
||||
local tag_date
|
||||
tag_date=$(git for-each-ref --format='%(creatordate:short)' "refs/tags/$latest_tag")
|
||||
|
||||
if [ -z "$tag_date" ]; then
|
||||
date +"%Y.%-m.%-d"
|
||||
return
|
||||
fi
|
||||
|
||||
# Format as YYYY.M.D (no leading zeros for month/day)
|
||||
local year month day
|
||||
year=$(echo "$tag_date" | cut -d'-' -f1)
|
||||
month=$((10#$(echo "$tag_date" | cut -d'-' -f2)))
|
||||
day=$((10#$(echo "$tag_date" | cut -d'-' -f3)))
|
||||
|
||||
echo "${year}.${month}.${day}"
|
||||
}
|
||||
|
||||
new_version=$1
|
||||
|
||||
if [ -n "$IOS_APP_VERSION" ]; then
|
||||
# Manual override via environment variable
|
||||
ios_new_version=$IOS_APP_VERSION
|
||||
elif echo "$new_version" | grep -qE '(canary|nightly)'; then
|
||||
# Canary/nightly: use the date of the last stable/beta tag
|
||||
ios_new_version=$(get_ios_version_from_git)
|
||||
else
|
||||
# Stable/beta release: use today's date
|
||||
ios_new_version=$(date +"%Y.%-m.%-d")
|
||||
fi
|
||||
|
||||
echo "iOS MARKETING_VERSION: $ios_new_version (app version: $new_version)"
|
||||
|
||||
update_app_version_in_helm_charts ".github/helm/affine/Chart.yaml" "$new_version"
|
||||
update_app_version_in_helm_charts ".github/helm/affine/charts/graphql/Chart.yaml" "$new_version"
|
||||
update_app_version_in_helm_charts ".github/helm/affine/charts/front/Chart.yaml" "$new_version"
|
||||
|
||||
update_app_stream_version "packages/frontend/apps/electron/resources/affine.metainfo.xml" "$new_version"
|
||||
|
||||
update_ios_marketing_version "packages/frontend/apps/ios/App/App.xcodeproj/project.pbxproj" "$ios_new_version"
|
||||
14
scripts/setup/global.ts
Normal file
14
scripts/setup/global.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { setupGlobal } from '@affine/env/global';
|
||||
import { getBuildConfig } from '@affine-tools/utils/build-config';
|
||||
import { Package } from '@affine-tools/utils/workspace';
|
||||
|
||||
globalThis.BUILD_CONFIG = getBuildConfig(new Package('@affine/web'), {
|
||||
mode: 'development',
|
||||
channel: 'canary',
|
||||
});
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.location.search = '?prefixUrl=http://127.0.0.1:3010/';
|
||||
}
|
||||
|
||||
setupGlobal();
|
||||
12
scripts/setup/lit.ts
Normal file
12
scripts/setup/lit.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { vi } from 'vitest';
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
// Refs: https://github.com/jsdom/jsdom/blob/master/lib/jsdom/living/custom-elements/CustomElementRegistry-impl.js
|
||||
const customElements = {
|
||||
define: vi.fn(),
|
||||
get: vi.fn(),
|
||||
whenDefined: vi.fn(),
|
||||
upgrade: vi.fn(),
|
||||
};
|
||||
vi.stubGlobal('customElements', customElements);
|
||||
}
|
||||
12
scripts/setup/polyfill.ts
Normal file
12
scripts/setup/polyfill.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/* oxlint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
Promise.withResolvers ??= function withResolvers() {
|
||||
var a,
|
||||
b,
|
||||
c = new this(function (resolve, reject) {
|
||||
a = resolve;
|
||||
b = reject;
|
||||
});
|
||||
return { resolve: a, reject: b, promise: c };
|
||||
};
|
||||
14
scripts/setup/vi-mock.ts
Normal file
14
scripts/setup/vi-mock.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { vi } from 'vitest';
|
||||
|
||||
vi.mock('lottie-web', () => ({
|
||||
default: {},
|
||||
}));
|
||||
|
||||
if (typeof window !== 'undefined' && HTMLCanvasElement) {
|
||||
// @ts-expect-error allow vitest global mock
|
||||
HTMLCanvasElement.prototype.getContext = () => {
|
||||
return {
|
||||
fillRect: vi.fn(),
|
||||
};
|
||||
};
|
||||
}
|
||||
3
scripts/vitest-global.js
Normal file
3
scripts/vitest-global.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export const setup = () => {
|
||||
process.env.TZ = 'Asia/Singapore';
|
||||
};
|
||||
Reference in New Issue
Block a user