feat: add registries index (#8126)

* feat: add registries index

* ci: update workflow

* ci: update

* fix

* debug

* ci: debug

* debug

* fix: build

* refactor
This commit is contained in:
shadcn
2025-09-03 08:24:02 +04:00
committed by GitHub
parent 851c0fa0d1
commit 62c41c3271
5 changed files with 152 additions and 1 deletions

View File

@@ -0,0 +1,88 @@
name: Validate Registries
on:
pull_request:
paths:
- "apps/v4/public/r/registries.json"
push:
branches:
- main
paths:
- "apps/v4/public/r/registries.json"
jobs:
validate:
runs-on: ubuntu-latest
name: pnpm validate:registries
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 20
- uses: pnpm/action-setup@v4
name: Install pnpm
id: pnpm-install
with:
version: 9.0.6
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
run: |
echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- name: Build packages
run: pnpm build --filter=shadcn
- name: Validate registries
id: validate
run: |
pnpm --filter=v4 validate:registries
echo "validation_passed=$?" >> $GITHUB_ENV
continue-on-error: true
- name: Add label to PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const validationPassed = '${{ env.validation_passed }}' === '0';
const label = validationPassed ? 'registries: valid' : 'registries: invalid';
const oppositeLabel = validationPassed ? 'registries: invalid' : 'registries: valid';
// Remove opposite label if it exists
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
name: oppositeLabel
});
} catch (e) {
// Label might not exist, that's ok
}
// Add the appropriate label
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: [label]
});

View File

@@ -14,6 +14,7 @@
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache",
"registry:build": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/build-registry.mts && prettier --log-level silent --write \"registry/**/*.{ts,tsx,json,mdx}\" --cache",
"registry:capture": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/capture-registry.mts",
"validate:registries": "tsx --tsconfig ./tsconfig.scripts.json ./scripts/validate-registries.mts",
"postinstall": "fumadocs-mdx"
},
"dependencies": {

View File

@@ -0,0 +1,3 @@
{
"@alpine": "https://alpine-registry.vercel.app/r/{name}.json"
}

View File

@@ -0,0 +1,58 @@
import { promises as fs } from "fs"
import path from "path"
import { registrySchema } from "shadcn/schema"
import { z } from "zod"
const registriesIndexSchema = z.record(
z.string().regex(/^@[a-zA-Z0-9][a-zA-Z0-9-_]*$/),
z.string().refine((url) => url.includes("{name}"))
)
async function main() {
// 1. Validate the registries.json file.
const registriesFile = path.join(process.cwd(), "public/r/registries.json")
const content = await fs.readFile(registriesFile, "utf-8")
const data = JSON.parse(content)
const registries = registriesIndexSchema.parse(data)
// 2. Validate each registry endpoint.
const errors: string[] = []
for (const [name, url] of Object.entries(registries)) {
try {
const testUrl = url.replace("{name}", "registry")
const response = await fetch(testUrl)
if (!response.ok) {
errors.push(`${name}: HTTP ${response.status}`)
continue
}
const json = await response.json()
registrySchema.parse(json)
console.log(`${name}`)
} catch (error) {
if (error instanceof z.ZodError) {
errors.push(`${name}: ${error.message}`)
continue
}
errors.push(
`${name}: ${error instanceof Error ? error.message : String(error)}`
)
}
}
if (errors.length > 0) {
console.error("\n❌ Validation failed:")
errors.forEach((err) => console.error(` ${err}`))
process.exit(1)
}
console.log("\n✅ All registries passed validation.")
process.exit(0)
}
main().catch((error) => {
console.error("❌ Error:", error instanceof Error ? error.message : error)
process.exit(1)
})

View File

@@ -47,7 +47,8 @@
"pub:beta": "cd packages/shadcn && pnpm pub:beta",
"pub:release": "cd packages/shadcn && pnpm pub:release",
"test:dev": "turbo run test --filter=!shadcn-ui --force",
"test": "start-server-and-test v4:dev http://localhost:4000 test:dev"
"test": "start-server-and-test v4:dev http://localhost:4000 test:dev",
"validate:registries": "pnpm --filter=v4 validate:registries"
},
"packageManager": "pnpm@9.0.6",
"dependencies": {