mirror of
https://github.com/waaraawa/ByteGrid.git
synced 2026-07-22 06:41:47 +00:00
chore: add Obsidian scorecard preflight checks
This commit is contained in:
parent
e68a0f3733
commit
98e42aea3d
7 changed files with 6011 additions and 5 deletions
60
.github/workflows/release.yml
vendored
Normal file
60
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
id-token: write
|
||||||
|
attestations: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: npm
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: npm test
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Prepare release assets
|
||||||
|
run: |
|
||||||
|
mkdir -p release
|
||||||
|
cp packages/obsidian-plugin/main.js release/main.js
|
||||||
|
cp packages/obsidian-plugin/styles.css release/styles.css
|
||||||
|
cp manifest.json release/manifest.json
|
||||||
|
|
||||||
|
- name: Attest release assets
|
||||||
|
uses: actions/attest-build-provenance@v2
|
||||||
|
with:
|
||||||
|
subject-path: release/*
|
||||||
|
|
||||||
|
- name: Ensure GitHub release exists
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: |
|
||||||
|
gh release view "${GITHUB_REF_NAME}" ||
|
||||||
|
gh release create "${GITHUB_REF_NAME}" \
|
||||||
|
--title "${GITHUB_REF_NAME}" \
|
||||||
|
--notes "Release ${GITHUB_REF_NAME}"
|
||||||
|
|
||||||
|
- name: Upload release assets
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
|
run: gh release upload "${GITHUB_REF_NAME}" release/* --clobber
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,6 +1,5 @@
|
||||||
# Dependencies
|
# Dependencies
|
||||||
node_modules/
|
node_modules/
|
||||||
package-lock.json
|
|
||||||
yarn.lock
|
yarn.lock
|
||||||
|
|
||||||
# Build outputs
|
# Build outputs
|
||||||
|
|
|
||||||
5852
package-lock.json
generated
Normal file
5852
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -10,6 +10,7 @@
|
||||||
"build": "npm run build --workspaces",
|
"build": "npm run build --workspaces",
|
||||||
"test": "npm run test --workspaces --if-present",
|
"test": "npm run test --workspaces --if-present",
|
||||||
"lint": "eslint . --ext .ts",
|
"lint": "eslint . --ext .ts",
|
||||||
|
"check:scorecard": "node scripts/check-scorecard.mjs",
|
||||||
"format": "prettier --write \"**/*.{ts,json,md}\"",
|
"format": "prettier --write \"**/*.{ts,json,md}\"",
|
||||||
"format:check": "prettier --check \"**/*.{ts,json,md}\"",
|
"format:check": "prettier --check \"**/*.{ts,json,md}\"",
|
||||||
"clean": "rm -rf packages/*/dist packages/*/node_modules node_modules"
|
"clean": "rm -rf packages/*/dist packages/*/node_modules node_modules"
|
||||||
|
|
@ -27,8 +28,9 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/jest": "^29.5.11",
|
"@types/jest": "^29.5.11",
|
||||||
"@types/node": "^20.10.6",
|
"@types/node": "^20.10.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
"@typescript-eslint/eslint-plugin": "^8.61.1",
|
||||||
"@typescript-eslint/parser": "^6.17.0",
|
"@typescript-eslint/parser": "^8.61.1",
|
||||||
|
"esbuild": "^0.28.1",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.1.1",
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.10.6",
|
"@types/node": "^20.10.6",
|
||||||
"builtin-modules": "^3.3.0",
|
"builtin-modules": "^3.3.0",
|
||||||
"esbuild": "^0.19.11",
|
"esbuild": "^0.28.1",
|
||||||
"obsidian": "^1.4.16",
|
"obsidian": "^1.4.16",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-dark .bytegrid-source {
|
.theme-dark .bytegrid-source {
|
||||||
background-color: #374151 !important;
|
background-color: #374151;
|
||||||
color: #e5e7eb;
|
color: #e5e7eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
93
scripts/check-scorecard.mjs
Normal file
93
scripts/check-scorecard.mjs
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
const ROOT = process.cwd();
|
||||||
|
const IGNORED_DIRS = new Set(['coverage', 'dist', 'node_modules']);
|
||||||
|
|
||||||
|
const checks = [];
|
||||||
|
|
||||||
|
function addCheck(name, run) {
|
||||||
|
checks.push({ name, run });
|
||||||
|
}
|
||||||
|
|
||||||
|
function listFiles(dir, predicate = () => true) {
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||||
|
return entries.flatMap((entry) => {
|
||||||
|
const fullPath = path.join(dir, entry.name);
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
if (IGNORED_DIRS.has(entry.name)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return listFiles(fullPath, predicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return predicate(fullPath) ? [fullPath] : [];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addCheck('No CSS !important usage', () => {
|
||||||
|
const cssFiles = listFiles(path.join(ROOT, 'packages'), (file) => file.endsWith('.css'));
|
||||||
|
const violations = cssFiles.flatMap((file) => {
|
||||||
|
const content = fs.readFileSync(file, 'utf8');
|
||||||
|
return content
|
||||||
|
.split('\n')
|
||||||
|
.map((line, index) => ({ file, line, lineNumber: index + 1 }))
|
||||||
|
.filter(({ line }) => line.includes('!important'));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (violations.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const details = violations
|
||||||
|
.map(({ file, lineNumber }) => `${path.relative(ROOT, file)}:${lineNumber}`)
|
||||||
|
.join('\n');
|
||||||
|
throw new Error(`Avoid !important in plugin CSS:\n${details}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
addCheck('Committed npm lockfile exists', () => {
|
||||||
|
const lockfile = path.join(ROOT, 'package-lock.json');
|
||||||
|
|
||||||
|
if (!fs.existsSync(lockfile)) {
|
||||||
|
throw new Error('package-lock.json is required for reproducible dependency resolution');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addCheck('Release workflow includes artifact attestation', () => {
|
||||||
|
const workflowDir = path.join(ROOT, '.github', 'workflows');
|
||||||
|
const workflowFiles = listFiles(workflowDir, (file) => /\.(ya?ml)$/.test(file));
|
||||||
|
|
||||||
|
const hasAttestation = workflowFiles.some((file) => {
|
||||||
|
const content = fs.readFileSync(file, 'utf8');
|
||||||
|
return content.includes('actions/attest-build-provenance');
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!hasAttestation) {
|
||||||
|
throw new Error(
|
||||||
|
'release workflow should attest release assets with actions/attest-build-provenance'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const failures = [];
|
||||||
|
|
||||||
|
for (const check of checks) {
|
||||||
|
try {
|
||||||
|
check.run();
|
||||||
|
console.log(`PASS ${check.name}`);
|
||||||
|
} catch (error) {
|
||||||
|
failures.push({ name: check.name, error });
|
||||||
|
console.error(`FAIL ${check.name}`);
|
||||||
|
console.error(error instanceof Error ? error.message : String(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (failures.length > 0) {
|
||||||
|
process.exitCode = 1;
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue