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
18 changes: 18 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ updates:
labels:
- "dependencies"

- package-ecosystem: "npm"
directory: "/mcp/apache-projects-mcp"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
cooldown:
default-days: 7
semver-major-days: 21
semver-minor-days: 7
semver-patch-days: 3
groups:
npm-minor-patch:
update-types:
- "minor"
- "patch"
labels:
- "dependencies"

- package-ecosystem: "github-actions"
directory: "/"
schedule:
Expand Down
16 changes: 16 additions & 0 deletions .github/license-header.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
name: ponymail-mcp tests
name: MCP server tests

on:
push:
branches: ["main", "rbowen-ponymail-mcp"]
branches: ["main"]
paths:
- "mcp/ponymail-mcp/**"
- ".github/workflows/ponymail-mcp-tests.yml"
- "mcp/**"
- "scripts/check-licenses.mjs"
- ".github/workflows/mcp-tests.yml"
pull_request:
paths:
- "mcp/ponymail-mcp/**"
- ".github/workflows/ponymail-mcp-tests.yml"
- "mcp/**"
- "scripts/check-licenses.mjs"
- ".github/workflows/mcp-tests.yml"

permissions: {}

jobs:
test:
name: Test on Node ${{ matrix.node-version }}
name: ${{ matrix.project }} on Node ${{ matrix.node-version }}
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
Expand All @@ -24,11 +26,12 @@ jobs:
strategy:
fail-fast: false
matrix:
project: ["ponymail-mcp", "apache-projects-mcp"]
node-version: ["20", "22"]

defaults:
run:
working-directory: mcp/ponymail-mcp
working-directory: mcp/${{ matrix.project }}

steps:
- name: Checkout
Expand All @@ -42,7 +45,10 @@ jobs:
node-version: ${{ matrix.node-version }}

- name: Install dependencies
run: npm install --no-audit --no-fund
run: npm ci

- name: Run tests
run: npm test

- name: Check dependency licenses
run: npm run licenses
29 changes: 29 additions & 0 deletions .github/workflows/static-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Static checks

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

permissions: {}

jobs:
prek:
name: prek (pre-commit hooks)
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false

- name: Set up uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0

- name: Run prek
run: uvx prek run --all-files --show-diff-on-failure
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ asf-highlights/birthdays/
project-activity/DATA/
project-activity/REPORTS/
node_modules/
package-lock.json
mcp/apache-projects-mcp/node_modules/
__pycache__/
*.pyc
94 changes: 94 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# prek / pre-commit configuration.
# Docs: https://github.com/j178/prek and https://pre-commit.com/
#
# One-time setup (see AGENTS.md):
# uv tool install prek
# prek install -t pre-commit -t commit-msg -t pre-push
#
# Run manually:
# prek run --all-files # fast checks (headers, yaml, ...)
# prek run --all-files --hook-stage pre-push # full suite (tests, licenses, zizmor)

default_install_hook_types: [pre-commit, commit-msg, pre-push]

exclude: |
(?x)^(
(.*/)?node_modules/.*|
(.*/)?package-lock\.json|
(.*/)?LICENSE|
\.github/license-header\.txt
)$

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-merge-conflict
- id: check-case-conflict
- id: check-added-large-files
- id: check-executables-have-shebangs
- id: mixed-line-ending
args: [--fix=lf]

- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.37.2
hooks:
- id: check-github-workflows
- id: check-dependabot

- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.5.6
hooks:
- id: insert-license
name: insert license header (python/shell)
files: \.(py|sh)$
args:
- --license-filepath=.github/license-header.txt
- --comment-style=#
- id: insert-license
name: insert license header (javascript)
files: \.m?js$
args:
- --license-filepath=.github/license-header.txt
- --comment-style=//
- id: insert-license
name: insert license header (html)
files: \.html$
args:
- --license-filepath=.github/license-header.txt
- --comment-style=<!--| |-->

- repo: local
hooks:
- id: no-coauthored-by
name: reject Co-authored-by trailers
entry: scripts/check-no-coauthor.sh
language: script
stages: [commit-msg]

- id: mcp-tests
name: MCP server tests (pre-push)
entry: bash -c 'for d in mcp/*/; do (cd "$d" && npm test) || exit 1; done'
language: system
pass_filenames: false
files: ^mcp/
stages: [pre-push]

- id: license-allowlist
name: dependency license allowlist (pre-push)
entry: bash -c 'for d in mcp/*/; do node scripts/check-licenses.mjs "$d" || exit 1; done'
language: system
pass_filenames: false
stages: [pre-push]

- id: zizmor
name: zizmor GitHub Actions lint (pre-push)
entry: uvx zizmor .github/workflows
language: system
pass_filenames: false
files: ^\.github/
stages: [pre-push]
103 changes: 103 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# AGENTS.md

Guidance for AI coding agents (and humans) working in the `apache/comdev`
repository. Read this before making changes.

## Repository layout

| Path | What it is | Toolchain |
|------|------------|-----------|
| `mcp/ponymail-mcp/` | MCP server for Apache PonyMail archives | Node.js (≥20), npm |
| `mcp/apache-projects-mcp/` | MCP server for `projects.apache.org` data | Node.js (≥20), npm |
| `asf-highlights/` | ASF activity / birthday report scripts | Python via `uv` (PEP-723 inline scripts) |
| `project-activity/` | Project activity report script | Python via `uv` (PEP-723 inline scripts) |
| `scripts/` | Repo tooling (license allowlist check, git hooks) | Node / Bash |
| `.github/` | CI workflows, dependabot, security config | GitHub Actions |

## Attribution policy (ASF requirement — read this)

Commits produced with AI/agent assistance **MUST** be attributed with a
`Generated-by:` trailer that names **the agent and its version** (the agent that
made the change), optionally followed by the model:

```
Generated-by: <agent name> <version> [(model)]
```

Concrete example:

```
Generated-by: Claude Code 2.1.158 (Claude Opus 4.8)
```

**Do NOT add `Co-authored-by:` trailers.** The ASF does not attribute commits to
AI tools as co-authors. This is enforced by a `commit-msg` hook
(`scripts/check-no-coauthor.sh`) that rejects any commit message containing a
`Co-authored-by:` line — install the hooks (below) so the check runs locally.

## One-time setup

Install [`prek`](https://github.com/j178/prek) (a fast, drop-in pre-commit
runner) and wire up the git hooks:

```bash
uv tool install prek # or: pipx install prek
prek install -t pre-commit -t commit-msg -t pre-push
```

This installs three hook types:
- **pre-commit** — fast checks: license headers, trailing whitespace, YAML/JSON
validity, workflow + dependabot schema validation.
- **commit-msg** — rejects `Co-authored-by:` trailers (see policy above).
- **pre-push** — the full suite: MCP test suites, dependency license allowlist,
and `zizmor` GitHub Actions lint.

## Running the checks

Run the fast checks at any time:

```bash
prek run --all-files
```

**Run all pre-push checks before you push** (this is the gate CI enforces):

```bash
prek run --all-files --hook-stage pre-push
```

The pre-push hooks shell out to `npm` and `uvx`, so for them to pass you need
each MCP project installed. Equivalently, run per project:

```bash
cd mcp/ponymail-mcp # and mcp/apache-projects-mcp
npm ci # reproducible install from the committed lock file
npm test # unit tests
npm run licenses # dependency license allowlist check
```

## Conventions

- **License headers.** Every source file (`*.js`, `*.mjs`, `*.py`, `*.sh`,
`*.html`) must carry the Apache-2.0 header from `.github/license-header.txt`.
The `insert-license` pre-commit hook adds it automatically; for files with a
`#!` shebang or a PEP-723 (`# /// script`) block, the header goes *after*
those lines.
- **Dependency licenses.** New npm dependencies must use an ASF Category-A
license (see the allowlist in `scripts/check-licenses.mjs`). Vetted exceptions
go in a per-project `.license-allowlist-exceptions.json`.
- **Lock files are committed.** `package-lock.json` is tracked for reproducible
installs and license checks — commit it alongside `package.json` changes and
install with `npm ci`.
- **GitHub Actions** are SHA-pinned (with a `# vX.Y.Z` comment), use top-level
`permissions: {}` with minimal per-job grants, and set
`persist-credentials: false` on checkout. `zizmor` enforces this.
- **Python** scripts are self-contained PEP-723 `uv` scripts — run them with
`uv run <script>.py`; dependencies are declared inline, not in a requirements
file.

## Security tooling (CI)

CodeQL, OpenSSF Scorecard, `zizmor`, dependency-review, and Dependabot (with
release cooldowns) all run in CI under `.github/workflows/`. Local `prek` hooks
mirror the parts you can run before pushing.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@ Contents of this repository:

* asf-highlights - tools for finding foundation-wide activity
* project-activities - tools for project-specific activity

Loading
Loading