Skip to content
Open
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
31 changes: 31 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Bug report
description: Report a reproducible problem with a Beatrice project.
title: "Bug: "
body:
- type: markdown
attributes:
value: For security vulnerabilities, use the private reporting option on the repository's Security tab.
- type: input
id: version
attributes:
label: Version and platform
description: Include the app version or commit, OS and relevant hardware or browser.
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
validations:
required: true
- type: textarea
id: behavior
attributes:
label: Expected and actual behavior
validations:
required: true
- type: textarea
id: logs
attributes:
label: Relevant logs or screenshots
description: Redact tokens, personal data and sensitive audio.
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: Report a security vulnerability
url: https://github.com/Project-Beatrice-V2/.github/blob/main/SECURITY.md
about: Follow the private reporting instructions for the affected repository.
14 changes: 14 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: '/'
schedule:
interval: weekly
day: monday
time: '05:00'
timezone: Etc/UTC
open-pull-requests-limit: 2
groups:
actions-minor-patch:
patterns: ["*"]
update-types: [minor, patch]
11 changes: 11 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## Summary

<!-- Describe what changed and why. Link any related issue. -->

## Verification

<!-- List the commands or manual steps you ran and their results. For audio or GPU changes, include the platform and hardware. -->

## Risk and rollout

<!-- Call out dependency, workflow, permission, installer or model changes and any follow-up needed. -->
35 changes: 35 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: CI

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

permissions: {}

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
configuration:
name: Configuration validation
runs-on: ubuntu-24.04
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: '3.12'
- run: python -m pip install check-jsonschema==0.39.0
- name: Validate workflow and community form schemas
run: |
check-jsonschema --builtin-schema vendor.github-workflows .github/workflows/*.yml
check-jsonschema --builtin-schema vendor.github-issue-forms .github/ISSUE_TEMPLATE/bug_report.yml
check-jsonschema --builtin-schema vendor.github-issue-config .github/ISSUE_TEMPLATE/config.yml
check-jsonschema --builtin-schema vendor.mergify .mergify.yml
34 changes: 34 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: CodeQL

on:
push:
branches: [main]
pull_request:
schedule:
- cron: '50 4 * * 1'
workflow_dispatch:

permissions: {}

concurrency:
group: codeql-${{ github.ref }}
cancel-in-progress: true

jobs:
analyze:
name: CodeQL analysis
runs-on: ubuntu-24.04
timeout-minutes: 35
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# This repository ships assets or documentation and GitHub Actions workflows.
- uses: github/codeql-action/init@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
with:
languages: actions
build-mode: none
- uses: github/codeql-action/analyze@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
58 changes: 58 additions & 0 deletions .github/workflows/pr-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: PR policy

on:
pull_request:
types: [opened, reopened, synchronize, edited, ready_for_review]

permissions: {}

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

jobs:
policy:
name: Review policy
if: '!github.event.pull_request.draft'
runs-on: ubuntu-24.04
timeout-minutes: 5
permissions:
pull-requests: read
steps:
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const pr = context.payload.pull_request;
const title = pr.title.trim();
const description = (pr.body ?? '')
.replace(/<!--[\s\S]*?-->/g, '')
.split('\n')
.filter(line => !/^\s*(?:#|[-*] \[)/.test(line))
.join(' ')
.trim();

if (pr.user.type !== 'Bot') {
if (title.length < 8 || /^(?:draft|wip)(?:\b|:)/i.test(title)) {
core.setFailed('Use a descriptive PR title and keep unfinished work in draft.');
}
if (description.length < 15) {
core.setFailed('Describe the change and how you verified it in the PR body.');
}
}

const files = await github.paginate(github.rest.pulls.listFiles, {
...context.repo,
pull_number: pr.number,
per_page: 100
});
const paths = files.flatMap(file => [file.filename, file.previous_filename].filter(Boolean));
const tests = /(^|\/)(tests?|__tests__)(\/|$)|(?:^|\/)test_[^/]+\.py$|\.(?:test|spec)\.[cm]?[jt]sx?$/i;
const source = /\.(?:[cm]?[jt]sx?|py|c|h|css|html|ipynb|sh|ps1|bat)$/i;
const risk = /(^\.github\/|(?:^|\/)(?:package(?:-lock)?\.json|(?:uv|poetry)\.lock|requirements[^/]*\.txt|pyproject\.toml|vercel\.json|(?:start|setup)[^/]*\.(?:sh|ps1|bat))$|\.(?:dll|exe|vst3|bin|zip)$)/i;

if (paths.some(path => source.test(path) && !tests.test(path)) && !paths.some(path => tests.test(path))) {
core.warning('Source changed without a test change. Add coverage where practical or describe manual verification.');
}
if (paths.some(path => risk.test(path)) || files.length < pr.changed_files) {
core.warning('Review dependency, automation, installer and binary changes with extra care.');
}
23 changes: 23 additions & 0 deletions .mergify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# yaml-language-server: $schema=https://docs.mergify.com/mergify-configuration-schema.json
pull_request_rules:
- name: Squash an approved README-only PR when a maintainer opts in
disabled:
reason: Enable after main has required reviews and checks, and the app is installed without bypass access.
conditions:
- base = main
- -draft
- label = automerge:docs
- -author = dependabot[bot]
- "#files = 1"
- files = README.md
- "#approved-reviews-by >= 1"
- "#changes-requested-reviews-by = 0"
- "#commits-behind = 0"
- "#check-failure = 0"
- check-success = @github-actions/Configuration validation
- check-success = @github-actions/Review policy
- check-success = @github-actions/CodeQL analysis
- check-success = @github-advanced-security/CodeQL
actions:
merge:
method: squash
9 changes: 9 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Contributing to Project Beatrice V2

Open the README in the repository you want to change and follow its platform and dependency setup. For projects with a Node lockfile, use `npm ci`. Keep dependency changes and their lockfile changes together.

Open pull requests against `main`. Give each PR a descriptive title and summarize the change, why it matters, and how you verified it. Use draft status while the work is in progress. For changes to application behavior, update the existing tests where practical. If the repository has no harness or the change needs audio hardware, record the platform, steps and result of your manual verification.

Keep generated installers, model weights, sample audio and credentials out of source changes unless the repository specifically manages those assets. Model contributions should follow the model repository's licensing and provenance requirements. Call out changes to dependencies, permissions, GitHub Actions, release scripts, launchers and bundled binaries in the PR so maintainers can review them closely.

Maintainers should review the diff and all applicable checks before merging. Report vulnerabilities privately as described in [SECURITY.md](SECURITY.md). See the [automation guide](docs/automation.md) for check coverage and maintainer setup.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[![CI](https://github.com/Project-Beatrice-V2/.github/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Project-Beatrice-V2/.github/actions/workflows/ci.yml) [![CodeQL](https://github.com/Project-Beatrice-V2/.github/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/Project-Beatrice-V2/.github/actions/workflows/codeql.yml) [![PR policy](https://github.com/Project-Beatrice-V2/.github/actions/workflows/pr-policy.yml/badge.svg?event=pull_request)](https://github.com/Project-Beatrice-V2/.github/actions/workflows/pr-policy.yml)

<div align="center">

<!-- Animated Typing SVG Header -->
Expand Down Expand Up @@ -170,3 +172,7 @@
<sub>Built with ❤️ by the Project Beatrice V2 Team • Released under the MIT License</sub>

</div>

## Repository automation

See the [organization automation guide](https://github.com/Project-Beatrice-V2/.github/blob/main/docs/automation.md) for checks, contribution policies, and integration setup.
7 changes: 7 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Security policy

Report a suspected vulnerability using **Security → Advisories → Report a vulnerability** in the affected repository. The report is private and goes to the maintainers. If the private report button is unavailable, contact a listed maintainer privately to arrange a disclosure channel.

Include the affected repository and version, platform, steps to reproduce, and the impact you observed. Redact credentials, personal data and sensitive audio. Keep exploit details out of public issues, pull requests and discussions while the report is under review.

We prioritize issues that affect the current release or the default branch. If you found the issue on an earlier release, include that version and whether the behavior persists on the latest version.
52 changes: 52 additions & 0 deletions docs/automation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Repository automation

Every repository runs CI on pull requests and on pushes to `main`. Pull requests also run a review policy check. The workflows run with read-only tokens except for CodeQL results uploads and the existing deployment or release jobs that need specific write permissions.

## Checks by repository

| Repository | CI verification | Dependabot ecosystems |
| --- | --- | --- |
| Beatrice-website | Node 24 and `npm ci`, Oxlint, TypeScript and Vite build, Python helper syntax | npm, GitHub Actions |
| Dataset Web UI (macOS and Windows) | Lockfile-based frontend build with TypeScript. Python 3.12 unit and FastAPI integration tests with CPU PyTorch and isolated SQLite and output directories | npm in `/frontend`, pip in `/voiceforge-backend`, GitHub Actions |
| Trainer (macOS and Windows) | JavaScript, Python and shell syntax. Build the Python wheel from the existing Hatchling package | pip at the root, uv in `/beatrice-trainer`, GitHub Actions |
| Voice Changer (macOS) | JavaScript, Python and shell syntax. Build the Apple Silicon DMG with the existing bundled Python and ad-hoc signing workflow | npm, pip, GitHub Actions |
| Voice Changer (Windows) | JavaScript and Python syntax. Build the installer and portable archive on Windows using the existing package script | npm, pip, GitHub Actions |
| Beatrice-colab | Validate Colab and Kaggle notebook structure with nbformat | GitHub Actions |
| Beatrice-voice-models | Parse model metadata and check ZIP integrity and paths without extraction | GitHub Actions |
| Organization `.github` | Validate Actions workflow, issue form and Mergify schemas | GitHub Actions |

The dataset repositories have the existing runnable unit and integration suites. The Windows voice changer's DLL diagnostic requires a separately built DLL and only prints on failure. It receives syntax checking in CI. GPU training, live audio devices, VST3 loading and hosted notebook execution still need their target environments. The standalone Python helpers in the website and the installs inside notebook cells have no tracked dependency manifest. Review their dependencies when changing those files.

The website stays connected to Vercel. Its GitHub Pages workflow publishes the legacy redirect. The Windows voice changer still publishes release assets only when a maintainer dispatches its release workflow for a tag. The packaging job has read-only access and passes files to a separate release upload job.

## Dependency and code scanning

Dependabot checks each listed ecosystem weekly. It groups minor and patch version bumps, keeps major updates separate, and limits the number of open version PRs. Python application requirements without lockfiles retain their existing constraints. Review matching trainer changes in both `requirements.txt` and `beatrice-trainer/pyproject.toml` when a shared dependency moves. The Dependency review check rejects newly introduced high or critical advisories in dependency graphs for application repositories. Existing alerts should be triaged separately in the Security tab.

CodeQL detects supported languages and scans on pull requests, pushes to `main` and a staggered weekly schedule. It uses buildless extraction. The profile, notebook and model repositories are scanned for GitHub Actions workflow code. Notebook cells and binary model contents fall outside CodeQL source analysis. If a repository has CodeQL default setup enabled later, use only one setup to avoid duplicate analyses. Use the advanced workflow in this rollout.

## Pull request policy

The Reviewpad app is in maintenance mode and accepts no new installations. The organization has no existing installation. The **Review policy** job checks titles and descriptions on ready-for-review PRs and flags source changes without test changes and changes to sensitive files. The warnings prompt human review. The job has read-only pull request access. [Reviewpad app status](https://github.com/apps/reviewpad)

## Enable SonarQube analysis

SonarQube workflows are prepared for the website, dataset apps, trainers and voice changers. Each repository scopes its own application code and excludes build outputs, dependency directories and generated artifacts. The dataset test directories are classified as tests. The existing suites do not produce configured coverage reports, so these scans do not ingest coverage.

1. Import the GitHub repository into SonarQube Cloud or create a project on a supported SonarQube Server. Connect the GitHub integration if you want PR decoration. For Cloud CI scans, turn off automatic analysis in the Sonar project.
2. Under **Settings → Secrets and variables → Actions**, add a project-scoped analysis token as the Actions secret `SONAR_TOKEN`.
3. Add the Actions variable `SONAR_PROJECT_KEY`. For Cloud, also add `SONAR_ORGANIZATION`. For a server or a Cloud region using a different host, set `SONAR_HOST_URL` to the HTTPS URL the runner can reach. The default host is `https://sonarcloud.io`.
4. Set `SONAR_ENABLED=true` and dispatch **SonarQube** from `main` to verify the scan and quality gate. Set `SONAR_PR_ANALYSIS=true` only if your Sonar plan supports PR analysis and you want it for same-repository PRs. Fork and Dependabot PRs keep the standard CI, Dependency review and CodeQL checks.
5. After the quality gate has run, copy its badge from the Sonar project's Information page if desired. Keep the Sonar job optional unless the required check can be produced for every PR you accept.

For a server with a private CA, add its certificate according to the scanner action's setup instructions. [SonarQube scan action](https://github.com/SonarSource/sonarqube-scan-action)

## Enable Mergify after branch rules are in place

The checked-in Mergify rule ships disabled. It only targets a ready, up-to-date PR that changes exactly `README.md`, has the maintainer-applied `automerge:docs` label and an approval, has no outstanding change requests, and passes the repository's CI, CodeQL scan and results, Review policy and applicable Dependency review checks. Any failing check blocks the rule. Dependabot PRs are excluded and dependency manifests cannot match the file constraint.

1. Install the Mergify GitHub App on selected repositories only. Keep the app out of all protection bypass lists.
2. On `main`, require pull requests, at least one approving review, dismissal of stale approvals, and the successful checks listed in that repository's `.mergify.yml`. Enable squash merging. Use GitHub's **Require code scanning results** rule for CodeQL and choose the alert severity that must block merges. Confirm existing protections and any additional required checks.
3. Use Mergify's configuration validator, then enable the rule by removing its `disabled` block in a reviewed PR. Create the `automerge:docs` label and apply it only after inspecting the change.

Mergify inherits applicable GitHub branch protection and ruleset requirements. [Mergify merge action](https://docs.mergify.com/workflow/actions/merge/)
Loading