Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/c3-frameworks-update-12713.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"create-cloudflare": patch
---

Update dependencies of "create-cloudflare"

The following dependency versions have been updated:

| Dependency | From | To |
| --------------- | ------ | ------ |
| @angular/create | 21.1.4 | 21.2.0 |
11 changes: 11 additions & 0 deletions .changeset/c3-frameworks-update-12715.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"create-cloudflare": patch
---

Update dependencies of "create-cloudflare"

The following dependency versions have been updated:

| Dependency | From | To |
| ---------- | ------ | ------ |
| create-vue | 3.21.1 | 3.22.0 |
11 changes: 11 additions & 0 deletions .changeset/c3-frameworks-update-12716.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"create-cloudflare": patch
---

Update dependencies of "create-cloudflare"

The following dependency versions have been updated:

| Dependency | From | To |
| ------------------- | ------ | ------ |
| create-react-router | 7.13.0 | 7.13.1 |
11 changes: 11 additions & 0 deletions .changeset/c3-frameworks-update-12719.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"create-cloudflare": patch
---

Update dependencies of "create-cloudflare"

The following dependency versions have been updated:

| Dependency | From | To |
| ----------- | ------- | ------- |
| create-vike | 0.0.581 | 0.0.591 |
7 changes: 7 additions & 0 deletions .changeset/images-binding-crud-operations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"miniflare": minor
---

Add Hosted Images CRUD operations to Images binding.

This is an experimental API that only works locally for the moment.
5 changes: 5 additions & 0 deletions .changeset/wicked-wombats-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudflare/vitest-pool-workers": patch
---

Fix resource leak where remote proxy sessions were not disposed during pool shutdown, causing vitest processes to hang.
68 changes: 68 additions & 0 deletions .codeowners
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# ============================================================
# Codeowners Plus - Code Ownership Rules
# ============================================================
# This file defines code ownership for the workers-sdk monorepo,
# enforced by Codeowners Plus (https://github.com/multimediallc/codeowners-plus).
#
# See CODEOWNERS.md for full documentation on how ownership works.
#
# Syntax:
# (no prefix) = primary owner (highest-priority match wins)
# & prefix = AND rule (additional required reviewer)
# ? prefix = optional/CC reviewer (non-blocking)
# Multiple teams on one line = OR (either can satisfy)
#
# Rules are relative to this file's directory (repo root).
# Unlike GitHub CODEOWNERS, `*.js` only matches in this directory;
# use `**/*.js` for recursive matching.
#
# Paths not matching any specific rule fall through to the default
# primary owner (currently @cloudflare/wrangler).
# ============================================================

# Default owner - ANT/Wrangler team owns everything
* @cloudflare/wrangler

# ----------------------------------------------------------
# D&C ownership (AND: requires wrangler + deploy-config)
# ----------------------------------------------------------
& packages/workers-shared/** @cloudflare/deploy-config

# ----------------------------------------------------------
# D1 ownership (AND: requires wrangler + d1)
# ----------------------------------------------------------
& packages/wrangler/src/api/d1/** @cloudflare/d1
& packages/wrangler/src/d1/** @cloudflare/d1
& packages/wrangler/src/__tests__/d1/** @cloudflare/d1

# ----------------------------------------------------------
# Cloudchamber ownership (AND: requires wrangler + cloudchamber)
# ----------------------------------------------------------
& packages/wrangler/src/cloudchamber/** @cloudflare/cloudchamber
& packages/wrangler/src/containers/** @cloudflare/cloudchamber
& packages/containers-shared/** @cloudflare/cloudchamber

# ----------------------------------------------------------
# Workers KV ownership (AND: requires wrangler + workers-kv)
# ----------------------------------------------------------
& packages/wrangler/src/kv/** @cloudflare/workers-kv
& packages/wrangler/src/__tests__/kv/** @cloudflare/workers-kv
& packages/miniflare/src/workers/kv/** @cloudflare/workers-kv
& packages/miniflare/test/plugins/kv/** @cloudflare/workers-kv

# ----------------------------------------------------------
# Workflows ownership (AND: requires wrangler + workflows)
# ----------------------------------------------------------
& packages/workflows-shared/** @cloudflare/workflows

# ----------------------------------------------------------
# Adding a new product team
# ----------------------------------------------------------
# Copy this template and fill in <feature> and <team>:
#
# # Product: <Name> (AND: requires wrangler + <team>)
# & packages/wrangler/src/<feature>/** @cloudflare/<team>
# & packages/wrangler/src/__tests__/<feature>/** @cloudflare/<team>
# & packages/miniflare/src/plugins/<feature>/** @cloudflare/<team>
# & packages/miniflare/src/workers/<feature>/** @cloudflare/<team>
# & packages/miniflare/test/plugins/<feature>/** @cloudflare/<team>
45 changes: 45 additions & 0 deletions .github/workflows/codeowners.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: "Code Owners"

# Re-evaluate when PRs are opened/updated, and when reviews are submitted/dismissed.
# Using pull_request_target (not pull_request) so the workflow has access to secrets
# for fork PRs. This is safe because:
# - The checkout is the BASE branch (ownership rules come from the protected branch)
# - PR head commits are fetched as git objects only (never checked out or executed)
# - The action only reads config files and calls the GitHub API
on:
pull_request_target:
types: [opened, reopened, synchronize, ready_for_review, labeled, unlabeled]
pull_request_review:
types: [submitted, dismissed]

concurrency:
group: codeowners-${{ github.event.pull_request.number }}
cancel-in-progress: true

permissions:
contents: read
issues: write
pull-requests: write

jobs:
codeowners:
name: "Run Codeowners Plus"
runs-on: ubuntu-latest
steps:
- name: "Checkout Base Branch"
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: "Fetch PR Head (for diff computation)"
run: git fetch origin +refs/pull/${{ github.event.pull_request.number }}/head
env:
GITHUB_TOKEN: "${{ secrets.CODEOWNERS_GITHUB_PAT }}"

- name: "Codeowners Plus"
uses: multimediallc/codeowners-plus@ff02aa993a92e8efe01642916d0877beb9439e9f # v1.9.0
with:
github-token: "${{ secrets.CODEOWNERS_GITHUB_PAT }}"
pr: "${{ github.event.pull_request.number }}"
verbose: true
quiet: ${{ github.event.pull_request.draft }}
139 changes: 139 additions & 0 deletions CODEOWNERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Code Ownership

This repository uses [Codeowners Plus](https://github.com/multimediallc/codeowners-plus) to enforce code ownership and review requirements. This replaces GitHub's native CODEOWNERS with more fine-grained control — specifically, the ability to require approval from **multiple teams** (AND rules) before a PR can merge.

## How It Works

### Overview

When a PR is opened, updated, or reviewed, the Codeowners Plus GitHub Action runs. It reads `.codeowners` and `codeowners.toml` from the **base branch** (not the PR), evaluates the ownership rules, and:

- Posts a PR comment listing which teams need to approve
- Requests reviews from those teams
- Sets a **required status check** ("Run Codeowners Plus") that passes only when all ownership rules are satisfied

The native GitHub `CODEOWNERS` file is not involved in enforcement.

### Key Difference from Native CODEOWNERS

| Feature | Native GitHub CODEOWNERS | Codeowners Plus |
| ------------------------ | --------------------------------- | ------------------------------------------------------------------------------- |
| Multiple teams on a path | **OR** — any one team can approve | **AND** via `&` prefix — all listed teams must approve |
| Path matching for `*.js` | Matches anywhere in repo | Matches only in the `.codeowners` file's directory; use `**/*.js` for recursive |
| Per-directory config | Single file only | `.codeowners` file in any directory (rules are relative to that directory) |
| Stale review dismissal | All-or-nothing | Smart — only dismisses when reviewer's owned files change |
| Optional reviewers | Not supported | `?` prefix — CC without blocking |

## Configuration Files

### `.codeowners` — Ownership Rules

Located at the repo root. Defines who owns what using path patterns and team handles. See the comments in the file itself for syntax details and a template for adding new product teams.

### `codeowners.toml` — Advanced Configuration

Located at the repo root. Controls enforcement behavior, ignored paths, and admin bypass.

Key settings:

| Setting | Purpose |
| -------------------------- | -------------------------------------------------------------------------- |
| `ignore` | Directories excluded from ownership checks (e.g. `.changeset`, `fixtures`) |
| `detailed_reviewers` | Show per-file owner breakdown in PR comments |
| `suppress_unowned_warning` | Don't warn about files with no owner |
| `enforcement.fail_check` | When `true`, the GHA check fails if rules aren't satisfied |
| `admin_bypass.enabled` | Allow admins to bypass by approving with "Codeowners Bypass" text |

### `CODEOWNERS` — Native GitHub File

The native GitHub `CODEOWNERS` file is kept for reference but is **not the enforcement mechanism**. Enforcement is handled by the Codeowners Plus required status check. All ownership logic lives in `.codeowners`.

### `.github/workflows/codeowners.yml` — GitHub Actions Workflow

A single workflow handles all events:

- `pull_request_target` — PR opened, updated, marked ready, labeled
- `pull_request_review` — review submitted or dismissed

Using `pull_request_target` (not `pull_request`) ensures the workflow has access to secrets for **fork PRs**. The checkout is always the base branch, so PR authors cannot modify ownership rules.

## Common Scenarios

### PR touches only wrangler-team-owned code

Example: changes to `packages/create-cloudflare/` or `packages/vite-plugin-cloudflare/`.

Only `@cloudflare/wrangler` approval is required.

### PR touches product-team-owned code

Example: changes to `packages/wrangler/src/d1/`.

**Both** `@cloudflare/wrangler` AND `@cloudflare/d1` must approve. Codeowners Plus will post a comment listing who still needs to approve and request reviews from both teams.

### PR touches multiple product areas

Example: changes to both `packages/wrangler/src/d1/` and `packages/wrangler/src/kv/`.

All three teams must approve: `@cloudflare/wrangler` + `@cloudflare/d1` + `@cloudflare/workers-kv`.

### PR touches ignored paths only

Example: changes only in `.changeset/` or `fixtures/`.

No ownership checks apply. The codeowners-plus check passes automatically.

### Draft PRs

The workflow runs in **quiet mode** for draft PRs:

- No PR comments posted
- No review requests sent
- The status check still runs for visibility

### Emergency bypass

Repository admins can bypass all requirements by submitting an **approval review** with the text "Codeowners Bypass" (case-insensitive). This creates an audit trail.

### Fork PRs

Fork PRs are fully supported. The workflow uses `pull_request_target` to run in the base repo context with access to secrets. The base branch is checked out (so ownership rules come from the protected branch), and the PR head is fetched as git objects only for diff computation. No fork code is executed.

## Adding a New Product Team

To add ownership for a new product team, add AND rules to `.codeowners`:

```bash
# Product: <Name> (AND: requires wrangler + <team>)
& packages/wrangler/src/<feature>/** @cloudflare/<team>
& packages/wrangler/src/__tests__/<feature>/** @cloudflare/<team>
& packages/miniflare/src/plugins/<feature>/** @cloudflare/<team>
& packages/miniflare/src/workers/<feature>/** @cloudflare/<team>
& packages/miniflare/test/plugins/<feature>/** @cloudflare/<team>
```

For example, to add R2 ownership:

```bash
# Product: R2 (AND: requires wrangler + r2)
& packages/wrangler/src/r2/** @cloudflare/r2
& packages/wrangler/src/__tests__/r2/** @cloudflare/r2
& packages/miniflare/src/plugins/r2/** @cloudflare/r2
& packages/miniflare/src/workers/r2/** @cloudflare/r2
& packages/miniflare/test/plugins/r2/** @cloudflare/r2
```

**Teams ready to add** (have source paths but no ownership entries yet):
R2, Queues, AI, Hyperdrive, Vectorize, Pipelines, SSL/Secrets Store, WVPC.

## Stale Review Handling

Codeowners Plus uses **smart dismissal**: when new commits are pushed to a PR, it only dismisses an approval if the files owned by that reviewer were changed. This avoids the frustration of GitHub's all-or-nothing stale review dismissal.

For this to work, the branch protection setting **"Dismiss stale pull request approvals when new commits are pushed"** must be **disabled**. Codeowners Plus handles dismissal itself.

## References

- [Codeowners Plus documentation](https://github.com/multimediallc/codeowners-plus)
- [Codeowners Plus action on GitHub Marketplace](https://github.com/marketplace/actions/codeowners-plus)
- [GitHub branch protection docs](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches)
23 changes: 23 additions & 0 deletions codeowners.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Codeowners Plus - Advanced Configuration
# See: https://github.com/multimediallc/codeowners-plus
# See: CODEOWNERS.md for full documentation

# Directories to ignore (no ownership checks, reduces review noise)
ignore = [".changeset", "fixtures"]

# Show detailed file-to-owner mapping in PR comments
detailed_reviewers = true

# Suppress warnings for intentionally unowned files (e.g. pnpm-lock.yaml)
suppress_unowned_warning = true

[enforcement]
# Enforcement is via a required GitHub status check ("Run Codeowners Plus").
# The check fails when ownership rules are not satisfied, blocking merge.
# No bot approval is used — the status check is the sole enforcement mechanism.
fail_check = true

[admin_bypass]
# Allow repo admins to bypass codeowner requirements in emergencies
# by submitting an approval review containing "Codeowners Bypass" text
enabled = true
4 changes: 2 additions & 2 deletions fixtures/vitest-pool-workers-examples/images/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# 🖼️ images
# images

This Worker returns information about an image that is POSTed to it.
This Worker returns information about an image that is POSTed to it and can perform Hosted Images CRUD operations.
8 changes: 4 additions & 4 deletions packages/create-cloudflare/src/frameworks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
"dependencies": {
"create-astro": "4.13.2",
"create-analog": "2.3.1",
"@angular/create": "21.1.4",
"@angular/create": "21.2.0",
"create-docusaurus": "3.9.2",
"create-hono": "0.19.4",
"create-next-app": "15.5.6",
"create-qwik": "1.19.0",
"create-vite": "8.3.0",
"create-rwsdk": "3.1.3",
"create-react-router": "7.13.0",
"create-react-router": "7.13.1",
"create-solid": "0.6.13",
"create-vike": "0.0.581",
"create-vue": "3.21.1",
"create-vike": "0.0.591",
"create-vue": "3.22.0",
"create-waku": "0.12.5-1.0.0-alpha.5-0",
"@tanstack/create-start": "0.59.8",
"gatsby": "5.16.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/create-cloudflare/templates/vue/workers/c3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const generate = async (ctx: C3Context) => {
await runFrameworkGenerator(ctx, [
ctx.project.name,
"--router",
lang === "ts" ? "--ts" : "",
lang === "ts" ? "--ts" : "--no-ts",
]);
logRaw("");
};
Expand Down
Loading
Loading