Thanks for your interest in contributing to GitProxy! This guide covers everything you need to get a local development environment running, understand the codebase, and submit high-quality pull requests.
For project governance, roles, and voting procedures, see the Governance section on the website.
- Prerequisites
- Getting Started
- Project Structure
- Development Workflow
- Testing
- Code Quality
- Configuration Schema
- Submitting a Pull Request
- Community
| Tool | Version | Notes |
|---|---|---|
| Node.js | 20.18.2+, 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 and integration tests (Vitest)
├── tests/e2e/ # End-to-end tests (Vitest + Docker)
├── cypress/ # UI tests (Cypress)
├── localgit/ # Local git server for E2E testing (see localgit/README.md)
├── packages/
│ └── git-proxy-cli/ # CLI package
├── plugins/ # Sample plugin packages
├── website/ # Documentation site (Docusaurus)
├── index.ts # CLI entry point
├── docker-compose.yml # Docker Compose for E2E environment
├── proxy.config.json # Default proxy configuration
├── config.schema.json # JSON Schema for configuration
├── vite.config.ts # Frontend build configuration
├── vitest.config.ts # Unit test configuration
└── vitest.config.e2e.ts # E2E test 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 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
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: vitest.config.ts
Test files are organized by module:
test/
├── processors/ # Proxy processor logic
├── db/ # Database operations
├── services/ # API and service tests
├── integration/ # Cross-module integration tests
├── 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: vitest.config.integration.ts
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: vitest.config.e2e.ts
The E2E environment is defined in 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 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:
# 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 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 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.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 Node.js (20, 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
All contributors must have a CLA on file with FINOS before PRs can be merged. Review the FINOS contribution requirements and submit the required CLA.
- 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