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
69 changes: 69 additions & 0 deletions .github/ISSUE_TEMPLATE/1_out_of_band_nomination.yml

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Out-of-Band Ladder Nomination
description: For existing organization members to nominate a new hire, partner engineer, or propose an off-cycle promotion.
title: "[Nomination]: @username for <Role>"
labels: ["nomination", "out-of-band"]
body:
- type: markdown
attributes:
value: |
### Out-of-Band Ladder Nomination
> [!NOTE]
> Standard promotions and new joiner invitations occur automatically during our data-driven **Quarterly Reviews**.
> Creating new issues and pull requests in `flutter/contributors` is restricted to organization members (`collaborators`); use this form as a sponsor for out-of-band additions (e.g. new Google/Partner hires) or expedited off-cycle role adjustments.

- type: input
id: candidate
attributes:
label: Candidate GitHub Handle
description: The GitHub username of the person being nominated.
placeholder: "@octocat"
validations:
required: true

- type: input
id: discord
attributes:
label: Candidate Discord Username
description: The candidate's Discord username so we can grant them the team member role and channel access on the Flutter Discord server.
placeholder: "octocat"
validations:
required: true

- type: dropdown
id: proposed_role
attributes:
label: Proposed Role
options:
- Maintainer (Flutter / Partners Team)
- Committer (Expedited Promotion)
- Reviewer (New Org Contributor)
validations:
required: true

- type: dropdown
id: affiliation
attributes:
label: Candidate Team / Domain
options:
- Flutter Team
- Partners Team (@flutter/partners)
- Community Contributor
validations:
required: true

- type: textarea
id: justification
attributes:
label: Contribution Summary & Justification
description: Provide background on the candidate's responsibilities, relevant merged PRs, reviews, or team role verification.
placeholder: "Candidate is joining the Flutter team as an engine maintainer..."
validations:
required: true

- type: checkboxes
id: sponsor_confirm
attributes:
label: Sponsor Confirmation
options:
- label: I am an active Flutter organization member nominating this candidate.
required: true
57 changes: 57 additions & 0 deletions .github/ISSUE_TEMPLATE/2_emeritus_reinstatement.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Dasher Emeritus Reinstatement Request

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do out-of-band and Dasher Emeritus need to be two separate forms?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. With the initial launch, many many contributors will be moved to emeritus. They and others on the team expressed concern that they felt like they would have to "start over again", and asked for a special re-entry point. Hence the separate special template to recognize their return.

description: For active organization members to sponsor a returning Dasher Emeritus rejoining the active contributor ladder off-cycle.
title: "[Reinstatement]: @username returning to active status"
labels: ["emeritus-reinstatement"]
body:
- type: markdown
attributes:
value: |
### Dasher Emeritus Reinstatement
> [!NOTE]
> Returning Dasher Emeriti who reach $\ge 10$ contributions are **automatically identified** during our data-driven **Quarterly Reviews**.
> Because creating new issues and pull requests in `flutter/contributors` is restricted to organization members (`collaborators`), off-cycle reinstatement requests must be opened by an active Flutter organization member acting as a sponsor (returning Emeriti can request a sponsor in `#hidden-chat` on Discord).

- type: input
id: username
attributes:
label: Emeritus GitHub Handle
description: The GitHub username of the returning Dasher Emeritus being sponsored for reinstatement.
placeholder: "@octocat"
validations:
required: true

- type: input
id: discord
attributes:
label: Emeritus Discord Username (if updated)
description: Dasher Emeriti retain Discord and Google Group access. Please provide their Discord username in case it has changed or needs to be updated in our records.
placeholder: "octocat"
validations:
required: false

- type: dropdown
id: requested_role
attributes:
label: Requested Ladder Role
options:
- Reviewer (@flutter/reviewers)
- Committer (@flutter/committers)
validations:
required: true

- type: textarea
id: recent_activity
attributes:
label: Recent Contributions
description: List recent pull requests, reviews, or triage activity since the Dasher Emeritus resumed contributing.
placeholder: "Links to recent PRs, issues, or reviews..."
validations:
required: true

- type: checkboxes
id: sponsor_confirm
attributes:
label: Sponsor Confirmation
options:
- label: I am an active Flutter organization member sponsoring this Dasher Emeritus for reinstatement.
required: true
31 changes: 31 additions & 0 deletions .github/ISSUE_TEMPLATE/3_quarterly_review_tracking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
name: Quarterly Community Review Tracking
about: Template for automated quarterly community ladder review issues.
title: "Quarterly Contributor Ladder Review - Q[X] [YYYY]"
labels: ["quarterly-review", "community-ladder"]
---

# Quarterly Community Contributor Ladder Review

This is the public tracking issue for the quarterly Flutter Contributor Ladder review.
Review criteria are defined in [LADDER.md](../../docs/LADDER.md).

## 1. 🎉 Recommended Promotions & New Community Joiners

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whitespace after heading (here and below).

You might want to have a markdown linter workflow:

from flutter/rfc:

      - name: Markdown Lint (PR Mode)
        if: github.event_name == 'pull_request' && steps.changed-rfcs.outputs.has_changes == 'true'
        uses: davidanson/markdownlint-cli2-action@05f32210e84442804257b2a6f20b273450ec8265 # v19
        with:
          globs: ${{ steps.changed-rfcs.outputs.files }}

      - name: Markdown Lint (Full Repository)
        if: github.event_name != 'pull_request'
        uses: davidanson/markdownlint-cli2-action@05f32210e84442804257b2a6f20b273450ec8265 # v19
        with:
          globs: 'rfc/**/*.md'

specific lints enabled/disabled; https://github.com/flutter/rfc/blob/main/.markdownlint.yaml

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eggcellent. Thanks!


*(Generated automatically by `dart run tool/quarterly_audit.dart --community`)*

> [!NOTE]
> If you are invited to join the ladder or promoted to a new tier above, please reply in this thread to accept and share your **Discord username** (if you do not already have the Discord team member role) so we can grant you team member channel access.

## 2. ✅ Active Role Retention

*(Generated automatically by `dart run tool/quarterly_audit.dart --community`)*

## 3. ⏳ 30-Day Grace Period (Proposed Demotions / Dasher Emeritus)

*(Generated automatically by `dart run tool/quarterly_audit.dart --community`)*

## 4. 📋 Callout for Unscripted & Qualitative Contributions

> [!IMPORTANT]
> If you have contributions that automated tracking does not index (issue triage, repro verification, [RFCs](https://github.com/flutter/rfc), design docs, mentoring), please reply in this thread with details before the 30-day grace period concludes.
19 changes: 19 additions & 0 deletions .github/ISSUE_TEMPLATE/4_partner_verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
name: Quarterly Partner Verification Tracking
about: Template for automated quarterly partner team verification issues.
title: "Quarterly Partner Team Verification - Q[X] [YYYY]"
labels: ["quarterly-review", "partner-verification"]
---

# Quarterly Partner Team Verification Review

Dedicated quarterly verification tracking issue for **@flutter/partners**.
The audit facilitator reaches out to each partner organization to confirm active status for their members below.

## 1. Active Partner Roster Verification

*(Generated automatically by `dart run tool/quarterly_audit.dart --partners`)*

## 2. Departures & Offboarding Sign-Off

- [ ] All partner memberships confirmed with partner organizations.
11 changes: 11 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: Flutter Contributor Ladder Guide
url: https://github.com/flutter/contributors/blob/main/docs/LADDER.md
about: Read about contributor tiers, criteria, responsibilities, and advancement pathways.
- name: Quarterly Review Process & Appeals
url: https://github.com/flutter/contributors/blob/main/docs/QUARTERLY_REVIEW.md
about: Learn how quarterly contributor reviews are conducted and how appeals are processed.
- name: Governance & Communication Channels
url: https://github.com/flutter/contributors/blob/main/docs/GOVERNANCE.md
about: Learn about GitHub teams, Discord channels, and onboarding to the announcement-only contributor Google Group.
49 changes: 47 additions & 2 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ on:
branches: [main]
workflow_dispatch:

permissions:
contents: read
permissions: {}

concurrency:
group: validate-${{ github.ref }}
Expand All @@ -18,10 +17,15 @@ jobs:
validate:
name: Validate Data Pipeline & Tests
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
persist-credentials: false

- name: Set up Dart SDK
uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c # v1.7.1
Expand All @@ -37,3 +41,44 @@ jobs:

- name: Run unit test suite
run: dart test

- name: Get Changed Markdown Files
id: changed-markdown
if: github.event_name == 'pull_request'
run: |
TARGET_REF="${BASE_REF:-main}"
TARGET_REF="${TARGET_REF#origin/}"
if git rev-parse --verify "origin/$TARGET_REF" >/dev/null 2>&1; then
BASE_TARGET="origin/$TARGET_REF"
elif git rev-parse --verify "$TARGET_REF" >/dev/null 2>&1; then
BASE_TARGET="$TARGET_REF"
else
echo "::error::Cannot resolve base branch ref 'origin/$TARGET_REF' or '$TARGET_REF'."
exit 1
fi
FILES=$(git diff --name-only --diff-filter=ACMR "$BASE_TARGET"...HEAD -- '*.md')
if [ -n "$FILES" ]; then
EOF_MARKER="EOF_$(openssl rand -hex 16)"
echo "has_changes=true" >> "$GITHUB_OUTPUT"
{
echo "files<<$EOF_MARKER"
echo "$FILES"
echo "$EOF_MARKER"
} >> "$GITHUB_OUTPUT"
else
echo "has_changes=false" >> "$GITHUB_OUTPUT"
fi
env:
BASE_REF: ${{ github.base_ref }}

- name: Markdown Lint (PR Mode)
if: github.event_name == 'pull_request' && steps.changed-markdown.outputs.has_changes == 'true'
uses: davidanson/markdownlint-cli2-action@05f32210e84442804257b2a6f20b273450ec8265 # v19
with:
globs: ${{ steps.changed-markdown.outputs.files }}

- name: Markdown Lint (Full Repository)
if: github.event_name != 'pull_request'
uses: davidanson/markdownlint-cli2-action@05f32210e84442804257b2a6f20b273450ec8265 # v19
with:
globs: '**/*.md'
6 changes: 6 additions & 0 deletions .markdownlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
default: true # Enable all standard markdownlint rules by default
MD013: false # Do not enforce line lengths (diff churning, table lengths, diagrams etc)
MD025:
front_matter_title: "" # Do not treat frontmatter title as H1 heading
MD033: false # Allow inline HTML (badges, centered logos/images, details/summary folds)
MD041: true # Enforce top-level heading after frontmatter
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<!-- when editing this file also update https://github.com/flutter/.github/blob/main/CONTRIBUTING.md -->
<!-- markdownlint-disable MD003 MD012 -->

Contributing to Flutter
=======================
Expand Down Expand Up @@ -132,7 +133,7 @@ presented.
5. [Flutter design doc template](https://flutter.dev/go/template),
which should be used when proposing a new technical design. This is a good
practice to do before coding more intricate changes.
See also our [guidance for writing design docs](https://github.com/flutter/flutter/blob/main/docs/contributing/Design-Documents.md).
See also [`flutter/rfc`](https://github.com/flutter/rfc) for project-wide RFC proposals and our [guidance for writing design docs](https://github.com/flutter/flutter/blob/main/docs/contributing/Design-Documents.md).

[![How to contribute to Flutter](https://img.youtube.com/vi/4yBgOBAOx_A/0.jpg)](https://www.youtube.com/watch?v=4yBgOBAOx_A)

Expand Down Expand Up @@ -241,4 +242,4 @@ Social events in the contributor community
Finally, one area where you could have a lot of impact is in contributing to social interactions among the Flutter contributor community itself.
This could take the form of organizing weekly video chats on our Discord, or planning tech talks from contributors, for example.
If this is an area that is of interest to you, please join our [Discord](https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md) and ping Hixie on the #hackers
channel!
channel!
7 changes: 7 additions & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Flutter Project Contributors

The Flutter project recognizes all contributors through the **Flutter Contributor Ladder**.

- For the active contributor directory and roster, see [ROSTER.md](ROSTER.md).
- For ladder tiers, criteria, and governance details, see [docs/LADDER.md](docs/LADDER.md).
- For historical AUTHORS archives, see [legacy_authors/](legacy_authors/).
67 changes: 53 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<!-- markdownlint-disable MD041 -->
<a href="https://flutter.dev/">
<h1 align="center">
<picture>
Expand All @@ -6,26 +7,64 @@
</picture>
</h1>
</a>
<!-- markdownlint-enable MD041 -->

# Flutter contributors

This repository tracks contributor ladder roles, project governance, and the contributor roster for the Flutter project.
This repository tracks contributor ladder roles, permissions, code review policies, and quarterly audits for the Flutter project.

## Current state
## Quick links

The automated pipeline in this repository collects a rolling 12-month record of contributions across all public repositories in the `flutter` GitHub organization.
- [Contributor roster](ROSTER.md) — active Maintainers, Committers, and Reviewers.
- [Dasher Emeritus directory](EMERITUS.md) — honored alumni who previously served on the contributor ladder.
- [Contributor ladder guide](docs/LADDER.md) — tier criteria, responsibilities, and permissions.
- [Code review workflow](docs/CODE_REVIEW_WORKFLOW.md) — approval requirements and PR landing rules.
- [Quarterly reviews](docs/QUARTERLY_REVIEW.md) — audit schedule, 30-day grace period, and appeals.
- [Data pipeline](docs/DATA_PIPELINE.md) — continuous 12-month activity collection and rolling 52-week storage.
- [Project governance](docs/GOVERNANCE.md) — team hierarchy, moderation scope, and communication channels.
- [Transition guide](docs/TRANSITION.md) — legacy member placement and historical AUTHORS archive.

- Merged pull requests, code reviews on merged PRs, and opened issues are tracked daily.
- Weekly snapshots are stored in `data/activity/`, with rolling 12-month totals aggregated in `data/activity_summary.json`.
- A scheduled workflow (`.github/workflows/sync_activity.yml`) runs daily at 02:17 UTC to sync activity and prune snapshots older than 52 weeks.
- See [docs/DATA_PIPELINE.md](docs/DATA_PIPELINE.md) for details on query design, rate limits, and bot filtering.
## Contributor ladder

## What is coming
```mermaid
graph TD
Contributor["1. Contributor<br/>(Read access • External)"] -->|"≥ 10 contributions"| Reviewer["2. Reviewer<br/>(Triage role • Org member)"]
Reviewer -->|"≥ 30 contributions (≥ 10 merged PRs)"| Committer["3. Committer<br/>(Write role • Org member)"]
Committer -.->|"Googler or Partner affiliation"| Maintainer["4. Maintainer<br/>(Write + moderation)"]

The repository will expand to host the complete contributor governance model and roster upon launch:
Reviewer -.->|"Inactivity (12m + 30d grace)"| Emeritus["Dasher Emeritus<br/>(Read access • External alumni)"]
Committer -.->|"Inactivity (12m + 30d grace)"| Emeritus
Maintainer -.->|"Departure / offboarding"| Emeritus
Emeritus -.->|"Resumed activity"| Reviewer
```

- Contributor ladder tiers (Contributor, Reviewer, Committer, Maintainer, and Dasher Emeritus).
- Public contributor roster and GitHub team synchronization.
- Code review workflows, landing requirements, and test exemption policies.
- Quarterly review audits, 30-day grace period tracking, and nomination workflows.
- Archival of repository `AUTHORS` files and contributor migration guides.
### Tiers

| Tier | GitHub role & team | 12-month rolling criteria | Permissions & responsibilities |
| :--- | :--- | :--- | :--- |
| **Contributor** | `Read` (External) | Any contribution (code, docs, issue triage, reproductions). | Open to anyone engaging with Flutter. |
| **Reviewer** | `Triage` (`@flutter/reviewers`) | $\ge 10$ contributions over 12 months. | First-pass PR reviews, issue triage and labeling, non-blocking approvals. |
| **Committer** | `Write` (`@flutter/committers`) | $\ge 30$ contributions with $\ge 10$ merged PRs over 12 months. | Repository write access, binding review approvals, and merge queue authority. |
| **Maintainer** | `Write` + Org Mod (`@flutter/googlers`, `@flutter/partners`, `@flutter/maintainers`) | All members of `@flutter/googlers` and `@flutter/partners`. | Domain stewardship and GitHub moderation permissions. |
| **Dasher Emeritus** | `Read` (External alumni) | Former ladder members with $< 10$ contributions over 12 months. | Removed from the GitHub org and listed in [EMERITUS.md](EMERITUS.md); retains Discord and Google Group access (limited to ladder members and Emeriti) to stay in touch and easily ramp back up if they return. |

Every active member on the ladder (`Reviewer`, `Committer`, `Maintainer`) is part of `@flutter/flutter-hackers` (parent team to `@flutter/reviewers`, `@flutter/committers`, and `@flutter/maintainers`). All Maintainers are either a Googler (`@flutter/googlers`) or a Partner (`@flutter/partners`, which has child teams per partner affiliation and remains top-level due to GitHub team nesting depth limits). Organization members outside of Google also belong to `@flutter/collaborators`.

## Tooling

| Tool | Command | Description |
| :--- | :--- | :--- |
| Activity sync | `dart run tool/sync_activity.dart` | Incremental daily sync of merged PRs, reviews, and issues. |
| Generate roster | `dart run tool/generate_roster.dart` | Compiles [ROSTER.md](ROSTER.md) and [EMERITUS.md](EMERITUS.md) from `data/contributors.yaml`. |
| Validate roster | `dart run tool/validate_roster.dart` | Validates YAML syntax, schema rules, and unique handles. |
| Prepare quarterly audit | `dart run tool/quarterly_audit.dart --prepare` | Vets nominated candidates, generates quarterly reports, and updates the roster for the quarterly PR. |
| Draft / open review issues | `dart run tool/quarterly_audit.dart --draft-issues` | Drafts (or opens with `--open-issues`) the public quarterly review issues from the generated reports. |
| Finalize quarterly PR | `dart run tool/quarterly_audit.dart --finalize` | Updates the quarterly PR after the 30-day review window with `--retain`, `--exclude`, and `--discord` adjustments. |
| Grace period check | `dart run tool/check_grace_period.dart` | Weekly check on open quarterly review issues: posts weekly countdown updates during the 30-day window and pings the assignee once 30 days have elapsed. |
| Check user | `dart run tool/check_user.dart <username>` | Evaluates 12-month metrics and eligibility for a contributor. |

## Communication channels

The broadcast-only `flutter-contributors` Google Group (no member posting, to avoid duplicating discussion spaces) is used to deliver announcements and send calendar invites—including our recurring Flutter Contributor Roundtable and the Dash Forum, where contributors can present and get feedback on their proposals ([`flutter/rfc`](https://github.com/flutter/rfc))—to ladder members and Dasher Emeriti. Onboarding is managed via a Google Form pinned in the `#hidden-chat` channel on Discord.

Real-time technical discussion and contributor ladder channels take place on the [Flutter Discord](https://discord.gg/flutter).
Loading
Loading