diff --git a/.github/workflows/ci-next-js.yml b/.github/workflows/ci-next-js.yml index 00ea05d..dfe1bba 100644 --- a/.github/workflows/ci-next-js.yml +++ b/.github/workflows/ci-next-js.yml @@ -21,7 +21,7 @@ on: - 'prettier.config.js' jobs: - build: + test: runs-on: ubuntu-latest steps: @@ -51,3 +51,86 @@ jobs: - name: Build run: pnpm build:next + + measure: + needs: test + runs-on: ubuntu-latest + + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref || github.ref }} + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '24' + # No cache - we want clean measurements + + - name: Measure install time + id: install + run: | + START=$(date +%s%N) + pnpm install --frozen-lockfile + END=$(date +%s%N) + ELAPSED=$((($END - $START) / 1000000)) + echo "time=$ELAPSED" >> $GITHUB_OUTPUT + echo "Install time: ${ELAPSED}ms" + + - name: Measure cold build time + id: cold_build + run: | + START=$(date +%s%N) + pnpm build:next + END=$(date +%s%N) + ELAPSED=$((($END - $START) / 1000000)) + echo "time=$ELAPSED" >> $GITHUB_OUTPUT + echo "Cold build time: ${ELAPSED}ms" + + - name: Measure warm build time + id: warm_build + run: | + START=$(date +%s%N) + pnpm build:next + END=$(date +%s%N) + ELAPSED=$((($END - $START) / 1000000)) + echo "time=$ELAPSED" >> $GITHUB_OUTPUT + echo "Warm build time: ${ELAPSED}ms" + + - name: Save CI stats + run: | + mkdir -p packages/starter-next-js + echo '{ + "installTimeMs": ${{ steps.install.outputs.time }}, + "coldBuildTimeMs": ${{ steps.cold_build.outputs.time }}, + "warmBuildTimeMs": ${{ steps.warm_build.outputs.time }}, + "timingMeasuredAt": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'", + "runner": "ubuntu-latest" + }' > packages/starter-next-js/.ci-stats.json + + - name: Commit CI stats + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add packages/starter-next-js/.ci-stats.json + + if git diff --staged --quiet; then + echo "No changes to commit" + exit 0 + fi + + git commit -m "Update CI stats for starter-next-js [skip ci]" + + # Push to the PR branch or main + if [ "${{ github.event_name }}" = "pull_request" ]; then + git push origin HEAD:${{ github.head_ref }} + else + git push + fi diff --git a/packages/starter-next-js/.ci-stats.json b/packages/starter-next-js/.ci-stats.json new file mode 100644 index 0000000..9293217 --- /dev/null +++ b/packages/starter-next-js/.ci-stats.json @@ -0,0 +1,7 @@ +{ + "installTimeMs": 6793, + "coldBuildTimeMs": 8357, + "warmBuildTimeMs": 7581, + "timingMeasuredAt": "2026-01-06T08:48:59Z", + "runner": "ubuntu-latest" +} diff --git a/packages/stats-generator/src/create-stats.ts b/packages/stats-generator/src/create-stats.ts index cfe9962..2d57462 100644 --- a/packages/stats-generator/src/create-stats.ts +++ b/packages/stats-generator/src/create-stats.ts @@ -3,6 +3,7 @@ import { join } from 'node:path' import { getStarterPackages } from './get-starter-packages.ts' import { packagesDir } from './constants.ts' import { saveStats } from './save-stats.ts' +import { getCIStats } from './get-ci-stats.ts' import type { FrameworkStats, PackageJson } from './types.ts' async function createStats() { @@ -21,9 +22,12 @@ async function createStats() { const prodCount = Object.keys(dependencies).length const devCount = Object.keys(devDependencies).length + const ciStats = await getCIStats(pkgDir) + const stats: FrameworkStats = { prodDependencies: prodCount, devDependencies: devCount, + ...(ciStats ?? {}), } await saveStats(pkgDir, stats) diff --git a/packages/stats-generator/src/get-ci-stats.ts b/packages/stats-generator/src/get-ci-stats.ts new file mode 100644 index 0000000..dfbd050 --- /dev/null +++ b/packages/stats-generator/src/get-ci-stats.ts @@ -0,0 +1,15 @@ +import { readFile } from 'node:fs/promises' +import { join } from 'node:path' +import { packagesDir } from './constants.ts' +import { CIStats } from './types.ts' + +export async function getCIStats(pkgDir: string) { + const ciStatsPath = join(packagesDir, pkgDir, '.ci-stats.json') + + try { + const content = await readFile(ciStatsPath, 'utf-8') + return JSON.parse(content) as CIStats + } catch (error) { + return null + } +} diff --git a/packages/stats-generator/src/types.ts b/packages/stats-generator/src/types.ts index e2f3897..4c0760c 100644 --- a/packages/stats-generator/src/types.ts +++ b/packages/stats-generator/src/types.ts @@ -1,4 +1,11 @@ -export interface FrameworkStats { +export interface CIStats { + installTimeMs?: number + coldBuildTimeMs?: number + warmBuildTimeMs?: number + timingMeasuredAt?: string +} + +export interface FrameworkStats extends CIStats { prodDependencies: number devDependencies: number }