diff --git a/.github/workflows/ci/package.json b/.github/workflows/ci/package.json index 3fdbbd6bf45..2eaed7537ea 100644 --- a/.github/workflows/ci/package.json +++ b/.github/workflows/ci/package.json @@ -1,5 +1,6 @@ { - "dependencies": { + "devDependencies": { + "@types/node": "^24.10.2", "typescript": "^5.9.3" } } diff --git a/.github/workflows/ci/tsconfig.json b/.github/workflows/ci/tsconfig.json index c68e78721ac..dca5bb226ee 100644 --- a/.github/workflows/ci/tsconfig.json +++ b/.github/workflows/ci/tsconfig.json @@ -6,6 +6,7 @@ "checkJs": true, "esModuleInterop": true, "module": "ESNext", + "types": ["node"], "skipLibCheck": true } } diff --git a/.github/workflows/sync-github-releases.yml b/.github/workflows/sync-github-releases.yml new file mode 100644 index 00000000000..101751a3d55 --- /dev/null +++ b/.github/workflows/sync-github-releases.yml @@ -0,0 +1,47 @@ +name: Publish new Release + +on: + push: + branches: + - main + paths: + - 'packages/vike/CHANGELOG.md' + workflow_dispatch: + +permissions: + contents: read + +jobs: + publish_package: + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write + environment: release + steps: + - uses: actions/checkout@v6 + - name: Install Bun + uses: oven-sh/setup-bun@v2 + with: + version: 1.2.19 + - name: Install pnpm + uses: pnpm/action-setup@v5 + with: + version: 10 + - name: Install Node + uses: actions/setup-node@v6 + with: + node-version: 24 + registry-url: 'https://registry.npmjs.org' + - name: Install modules + run: pnpm install --filter ./packages/vike + - name: Create NPM release + working-directory: ./packages/vike + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Create GitHub release + run: bun ./.github/workflows/sync-github-releases/sync-releases.ts + env: + GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/sync-github-releases/fixtures/changelog-telefunc.md b/.github/workflows/sync-github-releases/fixtures/changelog-telefunc.md new file mode 100644 index 00000000000..b3353d68f0e --- /dev/null +++ b/.github/workflows/sync-github-releases/fixtures/changelog-telefunc.md @@ -0,0 +1,31 @@ +## [0.1.2](https://github.com/brillout/telefunc/compare/v0.1.1...v0.1.2) (2022-01-25) + + +### Bug Fixes + +* improve TelefunctionError type ([41a572a](https://github.com/brillout/telefunc/commit/41a572a)) +* make error handling consistent between remote call and SSR call ([10edb6a](https://github.com/brillout/telefunc/commit/10edb6a)) + + + +## [0.1.1](https://github.com/brillout/telefunc/compare/0.1.0...0.1.1) (2022-01-24) + + +### Bug Fixes + +* enable isomorphic imports by refactoring source code file structure and adopting new TS/ESM/CJS strategy ([d0c182d](https://github.com/brillout/telefunc/commit/d0c182d)) +* warn user upon incorrect usage of isomorphic imports ([72700ca](https://github.com/brillout/telefunc/commit/72700ca)) + + + +# Telefunc (new 2021/2022 version) `0.1.0` + +Initial release. + +# Telefunc (old 2020 version) `0.0.26` + +See [github.com/brillout/telefunc-old](https://github.com/brillout/telefunc-old). + +# Wildcard API `v0.5.3` + +See [github.com/brillout/wildcard-api](https://github.com/brillout/wildcard-api). diff --git a/.github/workflows/sync-github-releases/fixtures/changelog-vike-react.md b/.github/workflows/sync-github-releases/fixtures/changelog-vike-react.md new file mode 100644 index 00000000000..4a9e68d8a51 --- /dev/null +++ b/.github/workflows/sync-github-releases/fixtures/changelog-vike-react.md @@ -0,0 +1,39 @@ +## [0.1.6](https://github.com/vikejs/vike-react/compare/v0.1.5...v0.1.6) (2023-06-24) + +### Bug Fixes + +- fix 'vike-react' type ([9fe6825](https://github.com/vikejs/vike-react/commit/9fe6825)) +- keep concrete types of vike-react config ([07a811f](https://github.com/vikejs/vike-react/commit/07a811f)) +- simplify type `Config` ([2fe1dcc](https://github.com/vikejs/vike-react/commit/2fe1dcc)) + +## [0.1.5](https://github.com/vikejs/vike-react/compare/v0.1.4...v0.1.5) (2023-05-26) + +### Bug Fixes + +- use latest vps version ([f35836e](https://github.com/vikejs/vike-react/commit/f35836e)) + +## [0.1.4](https://github.com/vikejs/vike-react/compare/v0.1.3...v0.1.4) (2023-05-26) + +### Bug Fixes + +- use latest vps commit ([d08e03d](https://github.com/vikejs/vike-react/commit/d08e03d)) + +## [0.1.3](https://github.com/vikejs/vike-react/compare/v0.1.2...v0.1.3) (2023-05-24) + +### Bug Fixes + +- fix type pointer ([c7841f2](https://github.com/vikejs/vike-react/commit/c7841f2)) + +## [0.1.2](https://github.com/vikejs/vike-react/compare/v0.1.1...v0.1.2) (2023-05-24) + +### Bug Fixes + +- fix ESM import paths - 2 ([5c881e5](https://github.com/vikejs/vike-react/commit/5c881e5)) + +## [0.1.1](https://github.com/vikejs/vike-react/compare/v0.1.0...v0.1.1) (2023-05-24) + +### Bug Fixes + +- fix ESM import paths ([60c4423](https://github.com/vikejs/vike-react/commit/60c4423)) + +## 0.1.0 (2023-05-24) diff --git a/.github/workflows/sync-github-releases/fixtures/changelog-vike-solid.md b/.github/workflows/sync-github-releases/fixtures/changelog-vike-solid.md new file mode 100644 index 00000000000..d160428d7e3 --- /dev/null +++ b/.github/workflows/sync-github-releases/fixtures/changelog-vike-solid.md @@ -0,0 +1,58 @@ +## [0.7.2](https://github.com/vikejs/vike-solid/compare/v0.7.1...v0.7.2) (2024-08-17) + + +### Bug Fixes + +* enable useConfig() after hydration ([#179](https://github.com/vikejs/vike-solid/issues/179)) ([0d28905](https://github.com/vikejs/vike-solid/commit/0d28905)) + + + +## [0.7.1](https://github.com/vikejs/vike-solid/compare/v0.7.0...v0.7.1) (2024-08-12) + + +### Bug Fixes + +* don't unnecessarily pass useConfig() values to client-side ([613bce3](https://github.com/vikejs/vike-solid/commit/613bce3)) + + +### Features + +* new [components `` and ``](https://vike.dev/useConfig#config-head) ([#104](https://github.com/vikejs/vike-solid/issues/104)) ([ed1c070](https://github.com/vikejs/vike-solid/commit/ed1c070)) + + + +# [0.7.0](https://github.com/vikejs/vike-solid/compare/v0.6.2...v0.7.0) (2024-08-06) + + +### Bug Fixes + +* avoid the default of title/lang setting to override Head setting ([1f91f16](https://github.com/vikejs/vike-solid/commit/1f91f16)) +* export Vike config only at /config ([d66c678](https://github.com/vikejs/vike-solid/commit/d66c678)) + + +### Features + +* [useConfig()](https://vike.dev/useConfig) ([88496ed](https://github.com/vikejs/vike-solid/commit/88496ed)) +* new hook [`onAfterRenderClient`](https://vike.dev/onAfterRenderClient) ([149f555](https://github.com/vikejs/vike-solid/commit/149f555)) + + +### BREAKING CHANGES + +* component `` removed: use `clientOnly()` helper instead https://vike.dev/clientOnly +* Update to `vike@0.4.191` or above. + + + +## [0.6.2](https://github.com/vikejs/vike-solid/compare/v0.6.1...v0.6.2) (2024-06-25) + + +### Features + +* Add streaming support for Web Stream ([69ac3cd](https://github.com/vikejs/vike-solid/commit/69ac3cd)) + + + +## [0.6.1](https://github.com/vikejs/vike-solid/compare/v0.6.0...v0.6.1) (2024-06-22) + + +**For previous versions, see [MIGRATION.md](https://github.com/vikejs/vike-solid/blob/main/MIGRATION.md).** diff --git a/.github/workflows/sync-github-releases/fixtures/changelog-vike-vue.md b/.github/workflows/sync-github-releases/fixtures/changelog-vike-vue.md new file mode 100644 index 00000000000..892c7d1ca7d --- /dev/null +++ b/.github/workflows/sync-github-releases/fixtures/changelog-vike-vue.md @@ -0,0 +1,33 @@ +## [0.2.3](https://github.com/vikejs/vike-vue/compare/v0.2.2...v0.2.3) (2023-09-08) + +### Bug Fixes + +- Fix `__name is not defined` ([11417ca](https://github.com/vikejs/vike-vue/commit/11417ca)) + +## [0.2.2](https://github.com/vikejs/vike-vue/compare/v0.2.1...v0.2.2) (2023-09-05) + +### Bug Fixes + +- Fix 'Error: Cannot find module' ([6b35d81](https://github.com/vikejs/vike-vue/commit/6b35d81)) + +## [0.2.1](https://github.com/vikejs/vike-vue/compare/v0.2.0...v0.2.1) (2023-08-29) + +- Fix peer dependency on `vite-plugin-ssr`. + +## [0.2.0](https://github.com/vikejs/vike-vue/compare/v0.1.1...v0.2.0) (2023-08-28) + +### Bug Fixes + +- Actually support `config.meta.ssr = false` ([3ee182a](https://github.com/vikejs/vike-vue/commit/3ee182a)) + +### Features + +- Add `Head` config option ([75cd700](https://github.com/vikejs/vike-vue/commit/75cd700)) + +## [0.1.1](https://github.com/vikejs/vike-vue/compare/v0.1.0...v0.1.1) (2023-08-20) + +- Add README content to [npm package](https://www.npmjs.com/package/vike-vue) + +## 0.1.0 (2023-08-20) + +- Initial version diff --git a/.github/workflows/sync-github-releases/fixtures/changelog-vike.md b/.github/workflows/sync-github-releases/fixtures/changelog-vike.md new file mode 100644 index 00000000000..56d01aea278 --- /dev/null +++ b/.github/workflows/sync-github-releases/fixtures/changelog-vike.md @@ -0,0 +1,59 @@ +# [0.1.0-beta.10](https://github.com/brillout/vite-plugin-ssr/compare/v0.1.0-beta.8...v0.1.0-beta.10) (2021-03-05) + + +### Bug Fixes + +* convert windows path to posix for micromatch ([cc9c405](https://github.com/brillout/vite-plugin-ssr/commit/cc9c405)), closes [#4](https://github.com/brillout/vite-plugin-ssr/issues/4) +* don't try to inject dynamic import polyfill ([fdffd37](https://github.com/brillout/vite-plugin-ssr/commit/fdffd37)) +* **boilerplates:** remove duplicated file ([4421aa6](https://github.com/brillout/vite-plugin-ssr/commit/4421aa6)) + + +### Features + +* allow render hook to return an object instead of HTML ([a649eaf](https://github.com/brillout/vite-plugin-ssr/commit/a649eaf)) +* support _500.page.js and improve error handling ([d492b9c](https://github.com/brillout/vite-plugin-ssr/commit/d492b9c)) +* support `html` tag composition ([9a57006](https://github.com/brillout/vite-plugin-ssr/commit/9a57006)) + + + +# [0.1.0-beta.9](https://github.com/brillout/vite-plugin-ssr/compare/v0.1.0-beta.8...v0.1.0-beta.9) (2021-03-01) + +### Bug Fixes + +* Fix released build + + + +# [0.1.0-beta.8](https://github.com/brillout/vite-plugin-ssr/compare/v0.1.0-beta.7...v0.1.0-beta.8) (2021-03-01) + + +### Bug Fixes + +* re-export default ([cd43e6e](https://github.com/brillout/vite-plugin-ssr/commit/cd43e6e)) +* use `in` operator only on objects ([819dfe1](https://github.com/brillout/vite-plugin-ssr/commit/819dfe1)) + + +### Features + +* remove html.sanitize and make sanitized automatic ([95d145c](https://github.com/brillout/vite-plugin-ssr/commit/95d145c)) + + +### BREAKING CHANGES + +* Removed `html.sanitize()`; simply directly insert the +string and vite-plugin-ssr will automatically sanitize it + + + +# [0.1.0-beta.7](https://github.com/brillout/vite-plugin-ssr/compare/v0.1.0-beta.6...v0.1.0-beta.7) (2021-02-28) + + +### Features + +* Pass `Page` to addContextProps. ([2512ee3](https://github.com/brillout/vite-plugin-ssr/commit/2512ee3)) + + + +# [0.1.0-beta.6](https://github.com/brillout/vite-plugin-ssr/tree/963afbafa5697d7745b6803bf1475b4aad7559c2) (2021-02-22) + +Initial public release diff --git a/.github/workflows/sync-github-releases/package.json b/.github/workflows/sync-github-releases/package.json new file mode 100644 index 00000000000..09faea87c5d --- /dev/null +++ b/.github/workflows/sync-github-releases/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "run": "bun ./sync-releases.ts ", + "try": "bun ./sync-releases.ts --dry-run" + }, + "devDependencies": { + "@types/node": "^24.10.2", + "typescript": "^5.9.3" + } +} diff --git a/.github/workflows/sync-github-releases/sync-releases.spec.ts b/.github/workflows/sync-github-releases/sync-releases.spec.ts new file mode 100644 index 00000000000..f71d55da3a9 --- /dev/null +++ b/.github/workflows/sync-github-releases/sync-releases.spec.ts @@ -0,0 +1,157 @@ +import { readFileSync } from 'node:fs' +import path from 'node:path' +import { describe, expect, it } from 'vitest' +import { getDefaultBranch, getReleasePlan, getReleaseSections, getRepository } from './sync-releases' + +function readFixture(name: string): string { + return readFileSync(path.join(__dirname, 'fixtures', name), 'utf8') +} + +describe('getReleaseSections()', () => { + it('maps changelog headings to version tags', () => { + const changelog = `## [1.0.1](https://example.org) (2026-03-01) + +### Features + +* Added release automation. + +## [1.0.0](https://example.org) (2026-02-28) + +### Bug Fixes + +* Fixed old release notes. +` + + expect(getReleaseSections(changelog)).toEqual({ + 'v1.0.1': '### Features\n\n* Added release automation.', + 'v1.0.0': '### Bug Fixes\n\n* Fixed old release notes.', + }) + }) + + it('parses oldest Vike entries (single # headings, pre-release versions)', () => { + const sections = getReleaseSections(readFixture('changelog-vike.md')) + expect(Object.keys(sections)).toEqual([ + 'v0.1.0-beta.10', + 'v0.1.0-beta.9', + 'v0.1.0-beta.8', + 'v0.1.0-beta.7', + 'v0.1.0-beta.6', + ]) + expect(sections['v0.1.0-beta.10']).toContain('### Features') + expect(sections['v0.1.0-beta.8']).toContain('### BREAKING CHANGES') + expect(sections['v0.1.0-beta.6']).toContain('Initial public release') + }) + + it('parses oldest Telefunc entries (trailing non-versioned sections)', () => { + const sections = getReleaseSections(readFixture('changelog-telefunc.md')) + expect(Object.keys(sections)).toEqual(['v0.1.2', 'v0.1.1']) + expect(sections['v0.1.2']).toContain('improve TelefunctionError type') + expect(sections['v0.1.1']).toContain('isomorphic imports') + }) + + it('parses oldest vike-vue entries (no-link headings, dash bullets)', () => { + const sections = getReleaseSections(readFixture('changelog-vike-vue.md')) + expect(Object.keys(sections)).toEqual(['v0.2.3', 'v0.2.2', 'v0.2.1', 'v0.2.0', 'v0.1.1']) + expect(sections['v0.2.1']).toContain('Fix peer dependency') + expect(sections['v0.2.0']).toContain('Add `Head` config option') + }) + + it('parses oldest vike-solid entries (single # headings, mixed formats)', () => { + const sections = getReleaseSections(readFixture('changelog-vike-solid.md')) + expect(Object.keys(sections)).toEqual(['v0.7.2', 'v0.7.1', 'v0.7.0', 'v0.6.2', 'v0.6.1']) + expect(sections['v0.7.0']).toContain('### BREAKING CHANGES') + expect(sections['v0.6.1']).toContain('MIGRATION.md') + }) + + it('parses oldest vike-react entries (no-link initial version)', () => { + const sections = getReleaseSections(readFixture('changelog-vike-react.md')) + expect(Object.keys(sections)).toEqual(['v0.1.6', 'v0.1.5', 'v0.1.4', 'v0.1.3', 'v0.1.2', 'v0.1.1']) + expect(sections['v0.1.6']).toContain("fix 'vike-react' type") + expect(sections['v0.1.1']).toContain('fix ESM import paths') + }) +}) + +describe('getReleasePlan()', () => { + it('creates the current release when missing and updates stale notes', () => { + const plan = getReleasePlan({ + defaultBranch: 'main', + versionTag: 'v1.0.1', + sections: { + 'v1.0.1': 'New release notes', + 'v1.0.0': 'Updated old notes', + 'v0.9.0': 'Existing notes', + }, + releases: [ + { id: 1, tag_name: 'v1.0.0', body: 'Outdated old notes' }, + { id: 2, tag_name: 'v0.9.0', body: 'Existing notes' }, + ], + }) + + expect(plan).toEqual({ + releaseToCreate: { + tag_name: 'v1.0.1', + target_commitish: 'main', + name: 'v1.0.1', + body: 'New release notes', + }, + releasesToUpdate: [{ release_id: 1, tag_name: 'v1.0.0', body: 'Updated old notes' }], + }) + }) + + it('updates the current release instead of creating a duplicate', () => { + const plan = getReleasePlan({ + defaultBranch: 'main', + versionTag: 'v1.0.1', + sections: { + 'v1.0.1': 'Fresh release notes', + }, + releases: [{ id: 3, tag_name: 'v1.0.1', body: 'Stale release notes' }], + }) + + expect(plan).toEqual({ + releaseToCreate: null, + releasesToUpdate: [{ release_id: 3, tag_name: 'v1.0.1', body: 'Fresh release notes' }], + }) + }) + + it('throws when the current version is missing from the changelog', () => { + expect(() => + getReleasePlan({ + defaultBranch: 'main', + versionTag: 'v1.0.1', + sections: {}, + releases: [], + }), + ).toThrow('Missing changelog entry for v1.0.1') + }) +}) + +describe('local fallbacks', () => { + it('falls back to the production repository when run locally', () => { + const previous = process.env.GITHUB_REPOSITORY + try { + delete process.env.GITHUB_REPOSITORY + expect(getRepository()).toEqual({ owner: 'vikejs', repo: 'vike' }) + } finally { + if (previous === undefined) { + delete process.env.GITHUB_REPOSITORY + } else { + process.env.GITHUB_REPOSITORY = previous + } + } + }) + + it('falls back to the main branch when run locally', () => { + const previous = process.env.GITHUB_DEFAULT_BRANCH + try { + delete process.env.GITHUB_DEFAULT_BRANCH + expect(getDefaultBranch()).toBe('main') + } finally { + if (previous === undefined) { + delete process.env.GITHUB_DEFAULT_BRANCH + } else { + process.env.GITHUB_DEFAULT_BRANCH = previous + } + } + }) +}) diff --git a/.github/workflows/sync-github-releases/sync-releases.ts b/.github/workflows/sync-github-releases/sync-releases.ts new file mode 100644 index 00000000000..2e61bcfbcd8 --- /dev/null +++ b/.github/workflows/sync-github-releases/sync-releases.ts @@ -0,0 +1,242 @@ +// Keeps GitHub releases aligned with `CHANGELOG.md`. +// => It derives release notes from `CHANGELOG.md`, creates the current release if needed (and any missing releases), and updates existing releases whose published notes are outdated (e.g. if CHANGELOG.md was manually edited). + +export { getReleasePlan } +export { getReleaseSections } +export { getDefaultBranch } +export { getRepository } + +import assert from 'node:assert' +import { readFile } from 'node:fs/promises' +import { createRequire } from 'node:module' +import path from 'node:path' +import { execSync } from 'node:child_process' +import { setTimeout } from 'node:timers/promises' +import { fileURLToPath } from 'node:url' +const require = createRequire(import.meta.url) +const { version } = require('../../../packages/vike/package.json') as { version: string } + +type Release = { + id: number + tag_name: string + body: string | null +} +type ReleaseSections = Record +type ReleaseCreateInput = { + tag_name: string + target_commitish: string + name: string + body: string +} +type ReleaseUpdateInput = { + release_id: number + tag_name: string + body: string +} + +async function main(): Promise { + // Local testing: + // GITHUB_TOKEN= bun ./.github/workflows/sync-github-releases/sync-releases.ts + // Dry-run (no GitHub token needed): + // bun ./.github/workflows/sync-github-releases/sync-releases.ts --dry-run + const dryRun = process.argv.includes('--dry-run') + const { owner, repo } = getRepository() + const defaultBranch = getDefaultBranch() + const versionTag = `v${version}` + const changelog = await readRepositoryFile('packages/vike/CHANGELOG.md') + const sections = getReleaseSections(changelog) + + if (dryRun) { + console.log(`Dry-run mode — no GitHub API calls will be made.`) + console.log(`Repository: ${owner}/${repo}`) + console.log(`Version tag: ${versionTag}`) + console.log(`Changelog sections found: ${Object.keys(sections).join(', ')}`) + assert(sections[versionTag], `Missing changelog entry for ${versionTag}`) + console.log(`\nRelease notes for ${versionTag}:\n${sections[versionTag]}`) + return + } + + const token = getGithubToken() + + // https://docs.github.com/en/rest/releases/releases#list-releases + const releases = await githubRequest(`/repos/${owner}/${repo}/releases?per_page=100`, { + token, + }) + + if (releases.length === 0) { + // Publish releases that are in CHANGELOG but not published + // Create release from oldest to newest, so that the release list + // is sorted by creation date in the same order as the changelog sections + const allTagReleasesToCreate = Object.keys(sections).reverse() + for (const tagName of allTagReleasesToCreate) { + await githubRequest(`/repos/${owner}/${repo}/releases`, { + token, + method: 'POST', + body: { + name: tagName, + tag_name: tagName, + target_commitish: defaultBranch, + body: sections[tagName], + }, + }) + console.log(`Created release ${tagName}`) + // Avoid hitting GitHub abuse rate limits + await setTimeout(500) + } + } else { + const { releaseToCreate, releasesToUpdate } = getReleasePlan({ defaultBranch, releases, sections, versionTag }) + + if (releaseToCreate) { + // https://docs.github.com/en/rest/releases/releases#create-a-release + await githubRequest(`/repos/${owner}/${repo}/releases`, { + token, + method: 'POST', + body: releaseToCreate, + }) + console.log(`Created release ${versionTag}`) + } + + for (const release of releasesToUpdate) { + // https://docs.github.com/en/rest/releases/releases#update-a-release + await githubRequest(`/repos/${owner}/${repo}/releases/${release.release_id}`, { + token, + method: 'PATCH', + body: { body: release.body }, + }) + console.log(`Updated release ${release.tag_name}`) + // Avoid hitting GitHub abuse rate limits + await setTimeout(500) + } + } +} + +function getReleaseSections(changelog: string): ReleaseSections { + const sections: ReleaseSections = {} + // Matches changelog headings: `## [0.4.257](...)` or `# [0.1.0-beta.6](...)` + const regex = /^##? \[(\d+\.\d+\.\d+[^\]]*)\]/gm + const matches: { version: string; index: number }[] = [] + + let match: RegExpExecArray | null + while ((match = regex.exec(changelog)) !== null) { + matches.push({ version: match[1], index: match.index }) + } + + matches.forEach((match, index) => { + const start = changelog.indexOf('\n', match.index) + const end = matches[index + 1]?.index ?? changelog.length + const notes = changelog.slice(start, end).trim() + sections[`v${match.version}`] = notes + }) + + return sections +} + +function getReleasePlan({ + defaultBranch, + releases, + sections, + versionTag, +}: { + defaultBranch: string + releases: Release[] + sections: ReleaseSections + versionTag: string +}): { + releaseToCreate: ReleaseCreateInput | null + releasesToUpdate: ReleaseUpdateInput[] +} { + const currentBody = sections[versionTag] + assert(currentBody, `Missing changelog entry for ${versionTag}`) + + const releaseToCreate = releases.some((release) => release.tag_name === versionTag) + ? null + : { + tag_name: versionTag, + target_commitish: defaultBranch, + name: versionTag, + body: currentBody, + } + + const releasesToUpdate = releases.flatMap((release) => { + const body = sections[release.tag_name] + if (!body || body === release.body) return [] + return [{ release_id: release.id, tag_name: release.tag_name, body }] + }) + + return { releaseToCreate, releasesToUpdate } +} + +function getRepository(): { owner: string; repo: string } { + const repository = process.env.GITHUB_REPOSITORY ?? getRepositoryFromGit() + const [owner, repo] = repository.split('/') + assert(owner && repo, `Invalid GITHUB_REPOSITORY value: ${repository}`) + return { owner, repo } +} + +function getRepositoryFromGit(): string { + const url = execSync('git remote get-url origin', { encoding: 'utf8' }).trim() + // Handles both https://github.com/owner/repo.git and git@github.com:owner/repo.git + const match = url.match(/github\.com[:/](.+?)(?:\.git)?$/) + assert(match, `Cannot parse GitHub repository from git remote: ${url}`) + return match[1] +} + +function getGithubToken(): string { + const token = process.env.GITHUB_TOKEN + if (!token) { + console.error( + [ + 'GITHUB_TOKEN is not set, run:', + ' GITHUB_TOKEN= pnpm run run', + 'Or dry-run (no token needed):', + ' pnpm run try', + ].join('\n'), + ) + process.exit(1) + } + return token +} + +function getDefaultBranch(): string { + return process.env.GITHUB_DEFAULT_BRANCH ?? 'main' +} + +async function readRepositoryFile(relativePath: string): Promise { + return readFile(path.join(getRepositoryRoot(), relativePath), 'utf8') +} + +function getRepositoryRoot(): string { + return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..') +} + +async function githubRequest( + pathname: string, + { body, method = 'GET', token }: { body?: unknown; method?: 'GET' | 'PATCH' | 'POST'; token: string }, +): Promise { + const apiUrl = process.env.GITHUB_API_URL ?? 'https://api.github.com' + const response = await fetch(new URL(pathname, apiUrl), { + method, + headers: { + Accept: 'application/vnd.github+json', + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + 'User-Agent': 'vike-sync-github-releases-workflow', + 'X-GitHub-Api-Version': '2022-11-28', + }, + body: body ? JSON.stringify(body) : undefined, + }) + + if (!response.ok) { + const errorBody = await response.text() + throw new Error( + `GitHub API request failed (${method} ${pathname}): ${response.status} ${response.statusText}\n${errorBody}`, + ) + } + + if (response.status === 204) return undefined as T + return (await response.json()) as T +} + +if (process.argv[1] === fileURLToPath(import.meta.url)) { + void main() +} diff --git a/.github/workflows/sync-github-releases/tsconfig.json b/.github/workflows/sync-github-releases/tsconfig.json new file mode 100644 index 00000000000..dca5bb226ee --- /dev/null +++ b/.github/workflows/sync-github-releases/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "strict": true, + "moduleResolution": "bundler", + "noImplicitAny": true, + "checkJs": true, + "esModuleInterop": true, + "module": "ESNext", + "types": ["node"], + "skipLibCheck": true + } +} diff --git a/README.md b/README.md index 663be729356..2d4a914c884 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ## Links :eyes: What is Vike: [vike.dev](https://vike.dev) -:clipboard: Version history & breaking changes: [CHANGELOG.md](/CHANGELOG.md) +:clipboard: Version history & breaking changes: [CHANGELOG.md](/packages/vike/CHANGELOG.md) :question: Get help: [vike.dev > FAQ > How can I reach out for help?](https://vike.dev/faq#how-can-i-reach-out-for-help) :green_heart: Contribute: [CONTRIBUTING.md](/CONTRIBUTING.md) diff --git a/docs/pages/migration/+Page.mdx b/docs/pages/migration/+Page.mdx index 94ac9efadfd..6392bba97e8 100644 --- a/docs/pages/migration/+Page.mdx +++ b/docs/pages/migration/+Page.mdx @@ -1,6 +1,6 @@ import { Link } from '@brillout/docpress' -For non-breaking version updates, see [CHANGELOG.md](https://github.com/vikejs/vike/blob/main/CHANGELOG.md) instead. +For non-breaking version updates, see [CHANGELOG.md](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md) instead. List of breaking version updates: - diff --git a/docs/pages/releases/+Page.mdx b/docs/pages/releases/+Page.mdx index 06541478988..418d52d7af8 100644 --- a/docs/pages/releases/+Page.mdx +++ b/docs/pages/releases/+Page.mdx @@ -8,7 +8,7 @@ import { Link } from '@brillout/docpress' ## See also -- [`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/CHANGELOG.md) +- [`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md) - [`vike-react` > `CHANGELOG.md`](https://github.com/vikejs/vike-react/blob/main/packages/vike-react/CHANGELOG.md) - [`vike-vue` > `CHANGELOG.md`](https://github.com/vikejs/vike-vue/blob/main/packages/vike-vue/CHANGELOG.md) - [`vike-solid` > `CHANGELOG.md`](https://github.com/vikejs/vike-solid/blob/main/CHANGELOG.md) diff --git a/docs/pages/releases/2024-06/+Page.mdx b/docs/pages/releases/2024-06/+Page.mdx index 2aa3bffac12..5c70dac42e6 100644 --- a/docs/pages/releases/2024-06/+Page.mdx +++ b/docs/pages/releases/2024-06/+Page.mdx @@ -39,7 +39,7 @@ What we have been working on in June 2024. **See also** -[`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/CHANGELOG.md) +[`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md) [`vike-react` > `CHANGELOG.md`](https://github.com/vikejs/vike-react/blob/main/packages/vike-react/CHANGELOG.md) [`vike-vue` > `CHANGELOG.md`](https://github.com/vikejs/vike-vue/blob/main/packages/vike-vue/CHANGELOG.md) [`vike-solid` > `CHANGELOG.md`](https://github.com/vikejs/vike-solid/blob/main/CHANGELOG.md) @@ -276,7 +276,7 @@ Major features we're currently working on: ## See also -- [`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/CHANGELOG.md) +- [`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md) - [`vike-react` > `CHANGELOG.md`](https://github.com/vikejs/vike-react/blob/main/packages/vike-react/CHANGELOG.md) - [`vike-vue` > `CHANGELOG.md`](https://github.com/vikejs/vike-vue/blob/main/packages/vike-vue/CHANGELOG.md) - [`vike-solid` > `CHANGELOG.md`](https://github.com/vikejs/vike-solid/blob/main/CHANGELOG.md) diff --git a/docs/pages/releases/2024-07/+Page.mdx b/docs/pages/releases/2024-07/+Page.mdx index 151b19c507f..39ed717909c 100644 --- a/docs/pages/releases/2024-07/+Page.mdx +++ b/docs/pages/releases/2024-07/+Page.mdx @@ -28,7 +28,7 @@ What we have been working on in July 2024. **See also** -[`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/CHANGELOG.md) +[`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md) [`vike-react` > `CHANGELOG.md`](https://github.com/vikejs/vike-react/blob/main/packages/vike-react/CHANGELOG.md) [`vike-vue` > `CHANGELOG.md`](https://github.com/vikejs/vike-vue/blob/main/packages/vike-vue/CHANGELOG.md) [`vike-solid` > `CHANGELOG.md`](https://github.com/vikejs/vike-solid/blob/main/CHANGELOG.md) @@ -170,7 +170,7 @@ We've been talking with the community to gather feedback for the upcoming new ma ## See also -- [`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/CHANGELOG.md) +- [`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md) - [`vike-react` > `CHANGELOG.md`](https://github.com/vikejs/vike-react/blob/main/packages/vike-react/CHANGELOG.md) - [`vike-vue` > `CHANGELOG.md`](https://github.com/vikejs/vike-vue/blob/main/packages/vike-vue/CHANGELOG.md) - [`vike-solid` > `CHANGELOG.md`](https://github.com/vikejs/vike-solid/blob/main/CHANGELOG.md) diff --git a/docs/pages/releases/2024-08/+Page.mdx b/docs/pages/releases/2024-08/+Page.mdx index 93215ac35e1..a00c651f451 100644 --- a/docs/pages/releases/2024-08/+Page.mdx +++ b/docs/pages/releases/2024-08/+Page.mdx @@ -21,7 +21,7 @@ import { BlogHeader } from '../../blog/BlogHeader' **See also** -[`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/CHANGELOG.md) +[`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md) [`vike-react` > `CHANGELOG.md`](https://github.com/vikejs/vike-react/blob/main/packages/vike-react/CHANGELOG.md) [`vike-vue` > `CHANGELOG.md`](https://github.com/vikejs/vike-vue/blob/main/packages/vike-vue/CHANGELOG.md) [`vike-solid` > `CHANGELOG.md`](https://github.com/vikejs/vike-solid/blob/main/CHANGELOG.md) @@ -71,7 +71,7 @@ Together with our upcoming structural improvements to [`vike-node`](https://gith ## See also -- [`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/CHANGELOG.md) +- [`vike` > `CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md) - [`vike-react` > `CHANGELOG.md`](https://github.com/vikejs/vike-react/blob/main/packages/vike-react/CHANGELOG.md) - [`vike-vue` > `CHANGELOG.md`](https://github.com/vikejs/vike-vue/blob/main/packages/vike-vue/CHANGELOG.md) - [`vike-solid` > `CHANGELOG.md`](https://github.com/vikejs/vike-solid/blob/main/CHANGELOG.md) diff --git a/docs/pages/versioning/+Page.mdx b/docs/pages/versioning/+Page.mdx index 994a32d17bb..dfbc0b8af70 100644 --- a/docs/pages/versioning/+Page.mdx +++ b/docs/pages/versioning/+Page.mdx @@ -3,11 +3,11 @@ Vike version updates that keep the leading digit (e.g. `0.4.x` => `0.4.y` or `1. ## `MINOR BREAKING CHANGES` -[`MINOR BREAKING CHANGES`](https://github.com/vikejs/vike/blob/main/CHANGELOG.md#minor-breaking-changes) can be introduced in any version update, even patch updates (e.g. `1.2.3` => `1.2.4`). +[`MINOR BREAKING CHANGES`](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md#minor-breaking-changes) can be introduced in any version update, even patch updates (e.g. `1.2.3` => `1.2.4`). They are expected to affect only very few users — you're unlikely to be one of them. So we recommend that you ignore `MINOR BREAKING CHANGES` unless updating breaks your app. -> If updating Vike breaks your app, check the [`CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/CHANGELOG.md) for any `MINOR BREAKING CHANGES`. If you experience a breaking change that isn't listed then reach out — we'll treat it as a regression and fix it. +> If updating Vike breaks your app, check the [`CHANGELOG.md`](https://github.com/vikejs/vike/blob/main/packages/vike/CHANGELOG.md) for any `MINOR BREAKING CHANGES`. If you experience a breaking change that isn't listed then reach out — we'll treat it as a regression and fix it. > Being able to introduce minor breaking changes in any version update allows us to *significantly* speed up Vike’s development. > diff --git a/CHANGELOG.md b/packages/vike/CHANGELOG.md similarity index 100% rename from CHANGELOG.md rename to packages/vike/CHANGELOG.md diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85b8e53c2ea..bcfc2558dfd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -31,7 +31,19 @@ importers: version: 4.1.4(@edge-runtime/vm@3.2.0)(@types/node@24.10.2)(vite@8.0.7(@types/node@24.10.2)(esbuild@0.27.3)(jiti@2.6.1)(terser@5.38.1)(tsx@4.20.6)) .github/workflows/ci: - dependencies: + devDependencies: + '@types/node': + specifier: ^24.10.2 + version: 24.10.2 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + + .github/workflows/sync-github-releases: + devDependencies: + '@types/node': + specifier: ^24.10.2 + version: 24.10.2 typescript: specifier: ^5.9.3 version: 5.9.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 6352536a565..a033b902d15 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -6,4 +6,4 @@ packages: - 'test/' - 'test/*' - 'test-deprecated-design/*' - - '.github/workflows/ci' + - '.github/workflows/*' diff --git a/vitest.config.ts b/vitest.config.ts index 546c6668c07..63c20f344af 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -9,7 +9,12 @@ export default defineConfig({ projects: [ { test: { - include: ['packages/**/*.spec.ts'], + include: ['packages/**/*.spec.ts', '.github/**/*.spec.ts'], + exclude: [ + '**/node_modules/**', + './packages/vike/src/node/vite/shared/resolveVikeConfigInternal/crawlPlusFilePaths/test-file-structure/**', + '.github/workflows/ci/prepare.spec.ts', + ], name: 'unit', env, },