This document describes the contribution process and governance policies of the FINOS GitProxy project. The project is also governed by the Linux Foundation Antitrust Policy, and the FINOS IP Policy, Code of Conduct, Collaborative Principles, and Meeting Procedures.
The project's Technical Charter defines its mission, scope, maintainer structure, intellectual property framework, and amendment process. Do not duplicate that material here.
Before making a contribution, please take the following steps:
- Check whether there's already an open issue related to your proposed contribution. If there is, join the discussion and propose your contribution there.
- If there isn't already a relevant issue, create one, describing your contribution and the problem you're trying to solve.
- Respond to any questions or suggestions raised in the issue by other developers.
- Fork the project repository and prepare your proposed contribution.
- Submit a pull request.
NOTE: Contributors must meet FINOS contribution requirements (CLA). Please read the FINOS Contribution Requirements before opening pull requests.
The project community consists of Contributors and Maintainers:
- A Contributor is anyone who submits a contribution to the project. (Contributions may include code, issues, comments, documentation, media, or any combination of the above.)
- A Maintainer is a Contributor who, by virtue of their contribution history, has been given write access to project repositories and may merge approved contributions.
- The Lead Maintainer is the project's interface with the FINOS team and Board. They are responsible for approving quarterly project reports and communicating on behalf of the project. The Lead Maintainer is elected by a vote of the Maintainers.
Anyone is welcome to submit a contribution to the project. The rules below apply to all contributions. (The key words "MUST", "SHALL", "SHOULD", "MAY", etc. in this document are to be interpreted as described in IETF RFC 2119.)
- All contributions MUST be submitted as pull requests, including contributions by Maintainers.
- All pull requests MUST be reviewed by a Maintainer (other than the Contributor) before being merged.
- Pull requests for non-trivial contributions SHOULD remain open for a review period sufficient to give all Maintainers a reasonable opportunity to review and comment on them.
- After the review period, if no Maintainer has an objection to the pull request, any Maintainer MAY merge it.
- If any Maintainer objects to a pull request, the Maintainers SHOULD try to come to consensus through discussion. If consensus cannot be reached, any Maintainer MAY call for a vote on the contribution using the Maintainer Voting process below.
GitProxy is used as a risk control in regulated financial institutions. To ensure broad consensus among the firms involved in project maintenance, pull requests that introduce new features (corresponding to feat: conventional commits), breaking changes (corresponding to a major version bump), or other changes that a Maintainer judges to be significant MUST be approved by at least one Maintainer from a different organisation than the contributing author before being merged.
This requirement does NOT apply to:
- Bug fixes
- Documentation updates
- Dependency patches and vulnerability remediation
- CI/infrastructure maintenance
- Refactoring that does not change external behaviour
- Other routine upkeep
Maintainers contributing such changes are expected to abide by the spirit of this rule — i.e., seek cross-firm review proactively rather than requiring it to be enforced.
The Maintainers MAY hold votes only when they are unable to reach consensus on an issue. Any Maintainer MAY call a vote on a contested issue, after which Maintainers SHALL have 36 hours to register their votes. Votes SHALL take the form of "+1" (agree), "-1" (disagree), "+0" (abstain). Issues SHALL be decided by the majority of votes cast. If there is only one Maintainer, they SHALL decide any issue otherwise requiring a Maintainer vote. If a vote is tied, FINOS (via help@finos.org) SHALL cast the deciding vote.
The Maintainers SHALL decide the following matters by consensus or, if necessary, a vote:
- Contested pull requests
- Election and removal of the Lead Maintainer
- Election and removal of Maintainers
All Maintainer votes MUST be carried out transparently, with all discussion and voting occurring in public, either:
- in comments associated with the relevant issue or pull request, if applicable;
- on the project mailing list or other official public communication channel; or
- during a regular, minuted community meeting.
If a contribution or project decision is contested, the following escalation process applies:
- Discussion in the relevant PR or issue thread to seek consensus among Maintainers.
- If unresolved, raise the matter at the next community meeting for open discussion.
- If still unresolved, any Maintainer MAY call a vote (36-hour window, majority decides per the Maintainer Voting process above).
- If the vote is tied, FINOS (via help@finos.org) SHALL cast the deciding vote.
A contributor whose pull request is closed may address the concerns raised and re-submit. If a contributor believes their contribution was unfairly rejected, they may invoke the dispute resolution process above.
Any Contributor who has made a substantial contribution to the project MAY apply (or be nominated) to become a Maintainer. The existing Maintainers SHALL decide whether to approve the nomination according to the Maintainer Voting process above.
The current Maintainer roster is recorded in MAINTAINERS.md. All changes to the maintainer list are managed publicly:
- Any addition, removal, or update MUST be submitted as a pull request to
MAINTAINERS.md. - If the change requires a Maintainer vote (e.g. election or removal of a Maintainer or the Lead Maintainer), the vote outcome MUST be documented in, or linked from, the pull request description or comments.
- This process creates a public audit trail of project leadership over time.
Whenever MAINTAINERS.md is updated with a change to maintainership, please email help@finos.org.
This document MAY be amended by a vote of the Maintainers according to the Maintainer Voting process above.
All contributors must have a CLA on file with FINOS before PRs can be merged. Review the FINOS contribution requirements and submit (or have your employer submit) the required CLA via EasyCLA.
Thanks for your interest in contributing to GitProxy! This section covers everything you need to get a local development environment running, understand the codebase, and submit high-quality pull requests.
- Prerequisites
- Getting Started
- Project Structure
- Development Workflow
- Testing
- Code Quality
- Configuration Schema
- Submitting a Pull Request
- Community
We actively support and test against the latest two LTS Node versions, currently 22 and 24. When a new LTS version rolls out (26, 28, etc.), we deprecate the oldest one.
| Tool | Version | Notes |
|---|---|---|
| Node.js | 22.13.1+, or 24.0.0+ | Check with node -v |
| npm | 8+ | Bundled with Node.js |
| Git | Any recent version | Must support HTTP/S |
| Docker & Docker Compose | Any recent version | Required for E2E tests only |
# Fork on GitHub, then clone your fork
git clone https://github.com/<your-username>/git-proxy.git
cd git-proxynpm installThis installs all dependencies for the server, UI, and CLI workspace packages. Husky git hooks are configured automatically via the prepare script.
# Run both the proxy server and the dashboard UI (recommended for development)
npm startThis starts two processes concurrently:
| Process | Command | URL | Description |
|---|---|---|---|
| Proxy server | npm run server |
http://localhost:8000 (proxy) / http://localhost:8080 (API) |
Express server handling git operations |
| Dashboard UI | npm run client |
http://localhost:3000 |
Vite dev server with hot module replacement |
You can also run them independently:
npm run server # Proxy server only
npm run client # Vite UI dev server only# Clone a repo through GitProxy
git clone http://localhost:8000/octocat/Hello-World.gitBy default, GitProxy blocks all pushes. To allow pushes for a specific repo, add it to proxy.config.json. See the Configuration docs for details.
git-proxy/
├── src/
│ ├── proxy/ # Core proxy logic (action chain, processors)
│ ├── service/ # Express app, API routes, authentication (Passport.js)
│ ├── db/ # Database abstraction (MongoDB + NeDB)
│ ├── config/ # Configuration loading and generated types
│ ├── ui/ # React dashboard (Material-UI)
│ ├── plugin.ts # Plugin base classes (PushActionPlugin, PullActionPlugin)
│ └── types/ # Shared TypeScript types
├── test/ # Unit, integration, and e2e tests (Vitest)
├── cypress/ # UI tests (Cypress)
├── packages/
│ └── git-proxy-cli/ # CLI package
├── plugins/ # Sample plugin packages
├── website/ # Documentation site (Docusaurus)
├── index.ts # CLI entry point
├── proxy.config.json # Default proxy configuration
├── config.schema.json # JSON Schema for configuration
└── vite.config.ts # Frontend build configuration
- Action chain: Git push/fetch requests flow through a chain of processors in
src/proxy/chain.ts - Plugin system: Extends the action chain with custom logic (see
src/plugin.ts) - Dual database: MongoDB for production state; NeDB for local file-based development (
.data/directory) - Authentication: Passport.js strategies (local, Active Directory, OpenID Connect)
npm run build # Full build: generate config types, build UI, compile TypeScript
npm run build-ts # Compile TypeScript server code to dist/
npm run build-ui # Build React frontend with Vite to build/
npm run build-validate # Check that UI files are correctly included in buildnpm run check-types # Type check everything (server + UI)
npm run check-types:server # Type check server code only (faster)Husky runs the following hooks automatically:
- pre-commit:
lint-stagedruns Prettier on staged files - commit-msg:
@commitlint/clienforces Conventional Commits format
Commit message examples:
feat: add new OIDC authentication strategy
fix: resolve race condition in push processor
docs: update testing guide with Vitest examples
test: add fuzz tests for repo name validation
To understand when your contribution will get merged upstream and published to NPM, see our Releases guide.
GitProxy has three test suites, each serving a different purpose.
Unit and integration tests use Vitest and are located in the test/ directory. These do not require Docker.
npm test # Run all unit tests once
npm run test-watch # Watch mode (re-runs on file changes)
npm run test-shuffle # Randomized execution order (detects test coupling)
npm run test-coverage # Run with coverage reportConfiguration: test/vitest.config.ts
Test files are organized by module:
test/
├── vitest.config.ts # Unit test configuration (`npm test`)
├── processors/ # Proxy processor logic
├── db/ # Database operations
├── services/ # API and service tests
├── integration/ # Cross-module integration tests
├── e2e/ # End-to-end tests (Vitest + Docker, includes forgejo/ and Compose)
├── plugin/ # Plugin system tests
├── preReceive/ # Git hook tests
└── fixtures/ # Binary test data for protocol-level tests
Some tests require a real MongoDB instance. These are guarded by the RUN_MONGO_TESTS environment variable and run separately from unit tests.
# Start MongoDB with Docker
docker run -d --name mongodb-test -p 27017:27017 mongo:7
# Run MongoDB integration tests
RUN_MONGO_TESTS=true npm run test:integration
# Cleanup
docker stop mongodb-test && docker rm mongodb-testConfiguration: test/vitest.integration.config.ts, test/integration/proxy.config.json
In CI, RUN_MONGO_TESTS is set automatically in the workflow that runs integration tests.
E2E tests perform real git operations against a Dockerized environment. They use Vitest with a separate config.
Prerequisites: Docker and Docker Compose must be running.
# Run E2E tests (builds containers, runs tests, tears down)
npm run test:e2e
# Watch mode for E2E development
npm run test:e2e:watchConfiguration: test/e2e/vitest.config.ts, test/e2e/proxy.config.json
The E2E environment is defined in test/e2e/docker-compose.yml and consists of three services:
| Service | Port | Description |
|---|---|---|
git-proxy |
8000, 8081 | GitProxy application under test |
mongodb |
27017 | MongoDB 7 instance |
git-server |
8443 | Apache-based git HTTP server with test repos (see test/e2e/localgit/) |
All services run in an isolated git-network Docker bridge network.
When developing or debugging E2E tests, you'll often want to keep the containers running between test runs rather than letting the test script tear them down.
From the repository root, either cd test/e2e first or set export COMPOSE_FILE=test/e2e/docker-compose.yml so the following commands find the Compose file:
# Start all services in the background
docker compose up -d
# Verify all three containers are running
docker compose ps
# Rebuild from scratch (e.g., after changing test/e2e/localgit/ or Dockerfile)
docker compose down -v
docker compose build --no-cache
docker compose up -dThe git server is initialized with two test repos:
| Repository | Path |
|---|---|
test-owner/test-repo.git |
Simple test repo with a README and text file |
e2e-org/sample-repo.git |
Sample project with a README, package.json, and LICENSE |
Two users are pre-configured:
| Username | Password | Purpose |
|---|---|---|
admin |
admin123 |
Full access to all repos |
testuser |
user123 |
Standard user for testing |
# Clone directly from the git server
git clone http://admin:admin123@localhost:8443/test-owner/test-repo.git
# Clone through GitProxy
git clone http://admin:admin123@localhost:8000/test-owner/test-repo.git
# Push a change
cd test-repo
echo "test" > test.txt
git add test.txt
git commit -m "test commit"
git push origin maindocker compose logs -f git-proxy # GitProxy application logs
docker compose logs -f git-server # Apache git server logs
docker compose logs -f mongodb # MongoDB logsIf services won't start or tests fail unexpectedly:
# Check service status
docker compose ps
# View logs for the failing service
docker compose logs git-server
# Nuclear option: tear down everything and rebuild
docker compose down -v
docker compose build --no-cache
docker compose up -dIf MongoDB connections fail:
docker compose exec mongodb mongosh --eval "db.adminCommand('ping')"The git server includes a data capture system that records raw git protocol data for every operation. This is useful for creating binary test fixtures (e.g., PACK files) for unit tests. See test/e2e/localgit/README.md for details on the capture system, PACK extraction tools, and fixture generation workflow.
Cypress tests exercise the dashboard UI end-to-end.
# Start the app first
npm start
# Then, in another terminal:
npm run cypress:open # Interactive test runner (recommended for development)
npm run cypress:run # Headless mode (used in CI)Configuration: cypress/cypress.config.js
Cypress tests live in cypress/e2e/ and use custom commands defined in cypress/support/commands.js (e.g., cy.login(username, password)).
Some test files include fuzz tests using fast-check to find edge-case bugs with randomized inputs. These run as part of the regular unit test suite (npm test).
All new code introduced in a PR must have over 80% patch coverage. This is enforced by CodeCov in CI.
# Generate a local coverage report
npm run test-coverageThe coverage report is written to ./coverage/. If your PR is below the threshold, check the CodeCov report on your PR for uncovered lines.
npm run lint # Run ESLint
npm run lint:fix # ESLint with auto-fix
npm run format # Format all files with Prettier
npm run format:check # Check formatting without modifying filesCI runs ESLint, Prettier, and TypeScript type checks on every PR (see .github/workflows/lint.yml).
GitProxy uses a JSON Schema (config.schema.json) to define and validate configuration. When adding or modifying config properties:
- Update
config.schema.jsonwith the new/changed properties - Regenerate TypeScript types:
npm run generate-config-types
- Regenerate the schema reference documentation for the website:
# Requires Python and json-schema-for-humans: # pip install json-schema-for-humans npm run gen-schema-doc
- Check for existing issues: Search open issues before starting work. If none exists, create one describing the change.
- Fork & branch: Create a feature branch from
main(e.g.,feat/my-featureorfix/my-bugfix). - Make your changes: Follow the code style enforced by ESLint and Prettier. Write tests for new functionality.
- Verify locally:
npm run check-types:server # Type check npm test # Unit tests npm run lint # Lint npm run format:check # Formatting
- Commit using Conventional Commits: The commit-msg hook validates this automatically.
- Push & open a PR: Target the
mainbranch. Fill in the PR template and link the relevant issue.
The following checks must pass before a PR can be merged:
- Unit tests: Run across a matrix of the latest 2 Node.js (22, 24) and MongoDB (6.0, 7.0, 8.0) versions on Ubuntu, plus a Windows build
- E2E tests: Docker-based end-to-end tests
- Cypress tests: UI end-to-end tests
- Lint & format: ESLint, Prettier, TypeScript type checks
- Commit lint: Conventional Commits validation
- Coverage: 80%+ patch coverage via CodeCov
- Security: CodeQL analysis, dependency review, OpenSSF Scorecard
See the CLA section in the Governance section above.
- Slack: #git-proxy on the FINOS Slack workspace
- Mailing list: git-proxy+subscribe@lists.finos.org
- Community meetings: Fortnightly on Mondays at 4PM BST (odd week numbers) via Zoom. Add to Google Calendar.
- Issues: github.com/finos/git-proxy/issues