Thank you for your interest in contributing to VacciChain! This document provides guidelines and instructions for contributing to our project.
- Local Setup
- Branching Strategy
- Branch Protection Rules
- Pull Request Process
- Commit Conventions
- Code of Conduct
- Docker Base Image Pinning
- Node.js 18+
- Python 3.11+
- Rust +
wasm32-unknown-unknowntarget - Soroban CLI
- Docker + Docker Compose
- Freighter Wallet (for testing)
-
Clone the repository
git clone https://github.com/dev-fatima-24/VacciChain.git cd VacciChain -
Copy environment configuration
cp .env.example .env # Fill in your Stellar keys and contract IDs -
Install backend dependencies
cd backend npm install cd ..
-
Install frontend dependencies
cd frontend npm install cd ..
-
Install Python service dependencies
cd python-service pip install -r requirements.txt cd ..
-
Deploy smart contract (if needed)
cd contracts make build make deploy cd ..
-
Run locally
# Terminal 1: Backend cd backend && npm run dev # Terminal 2: Frontend cd frontend && npm run dev # Terminal 3: Python service cd python-service && uvicorn main:app --port 8001
Or use Docker Compose:
docker compose up --build
We follow a feature branch workflow:
- main: Production-ready code. Protected branch, requires PR review.
- Feature branches:
feature/<description>orissues/<issue-numbers>- Example:
feature/openapi-specorissues/77-79-82-84 - Branch from
main - Prefix with issue numbers if addressing GitHub issues
- Example:
git checkout main
git pull origin main
git checkout -b issues/77-79-82-84The main branch is protected with the following rules enforced via GitHub branch protection settings:
| Rule | Setting |
|---|---|
Direct pushes to main |
Blocked — all changes must go through a PR |
| Required approving reviews | 1 — at least one team member must approve |
| Required status checks | All CI jobs must pass (contract, backend, frontend, python, all-tests) |
| Branch deletable | No — main cannot be deleted |
| Stale review dismissal | Enabled — new commits dismiss existing approvals |
- You cannot push directly to
main. Always create a feature branch and open a PR. - Your PR will not be mergeable until:
- At least one reviewer has approved it.
- All CI checks (tests, linting, security scans) have passed.
- If you push new commits after receiving an approval, the approval is automatically dismissed and re-review is required.
- The
mainbranch cannot be deleted or force-pushed under any circumstances.
To apply or update these rules, go to GitHub → Settings → Branches → Branch protection rules and configure the main branch with:
- ✅ Require a pull request before merging
- ✅ Require approvals: 1
- ✅ Dismiss stale pull request approvals when new commits are pushed
- ✅ Require status checks to pass before merging
- ✅ Require branches to be up to date before merging
- Add required checks:
All tests passed(theall-testsgate job inci.yml)
- ✅ Do not allow bypassing the above settings
- ✅ Restrict deletions
-
Ensure tests pass
# Backend cd backend && npm test # Contracts cd contracts && cargo test # Python service cd python-service && pytest
-
Run linters (if configured)
cd backend && npm run lint # if available
-
Update documentation if your changes affect user-facing features
-
Commit your changes using Conventional Commits
-
Push your branch
git push -u origin issues/77-79-82-84
-
Create a pull request on GitHub
- Use the PR template (auto-populated from
.github/pull_request_template.md) - Link related issues:
Closes #77, #79, #82, #84 - Provide a clear description of changes
- Include testing notes
- Use the PR template (auto-populated from
-
Address review feedback
- Make requested changes
- Push updates to the same branch
- Respond to comments
-
Merge once approved
- Use "Squash and merge" for single-commit PRs
- Use "Create a merge commit" for multi-commit PRs with logical separation
We follow Conventional Commits for clear, semantic commit messages.
<type>(<scope>): <subject>
<body>
<footer>
- feat: A new feature
- fix: A bug fix
- docs: Documentation changes
- style: Code style changes (formatting, missing semicolons, etc.)
- refactor: Code refactoring without feature changes
- perf: Performance improvements
- test: Adding or updating tests
- chore: Build, dependency, or tooling changes
Optional. Indicates the area affected:
backend,frontend,contracts,python-serviceauth,vaccination,verify,analytics#77,#79(issue numbers)
git commit -m "feat(backend): add OpenAPI spec generation"
git commit -m "fix(#77): resolve swagger endpoint routing"
git commit -m "docs(#79): add contributor onboarding guide"
git commit -m "test(contracts): add mint_vaccination tests"
git commit -m "chore: update dependencies"We are committed to providing a welcoming and inspiring community for all. We pledge to:
- Be respectful and inclusive
- Welcome diverse perspectives and experiences
- Focus on constructive feedback
- Respect confidentiality and privacy
- Use welcoming and inclusive language
- Be respectful of differing opinions and experiences
- Accept constructive criticism gracefully
- Focus on what is best for the community
- Show empathy towards other community members
- Harassment, discrimination, or intimidation
- Offensive comments related to personal characteristics
- Deliberate intimidation or threats
- Unwelcome sexual attention or advances
- Trolling, insulting, or derogatory comments
If you witness or experience unacceptable behavior, please report it to the maintainers at [contact email]. All reports will be reviewed and investigated.
All Docker base images in this project use pinned SHA256 digests to ensure reproducible builds. This means:
- Reproducibility: Every build with the same Dockerfile will produce identical results
- Security: We avoid accidentally pulling updated images with potential vulnerabilities
- Stability: Breaking changes in base images won't silently break our builds
- Auditability: We can track exactly which base image version was used in each build
Each FROM statement includes both a tag and a SHA256 digest:
FROM node:18.18.2-alpine@sha256:18a70ffe45b8a3db9e3e8dd85a92d7beab70d395e0d529ada0d9de0319c8b4d7This format ensures the exact image is pulled, not just any image with the 18.18.2-alpine tag.
- Image:
node:18.18.2-alpine - Digest:
sha256:18a70ffe45b8a3db9e3e8dd85a92d7beab70d395e0d529ada0d9de0319c8b4d7 - Location: backend/Dockerfile
- Node Builder:
node:18.18.2-alpine@sha256:18a70ffe45b8a3db9e3e8dd85a92d7beab70d395e0d529ada0d9de0319c8b4d7 - nginx Runtime:
nginx:1.25.3-alpine@sha256:41edf44158e0046487e614e118e9d1f0e0614a95a0c8f8e1ad826e8a9fb02a80 - Location: frontend/Dockerfile
- Image:
python:3.11.7-slim - Digest:
sha256:bae67dbbd3c2c9d94a3cf02c8a1cfc3c6f3c5d5e3d9b7195f8c0a06d09d4f5f2 - Location: python-service/Dockerfile
We use Renovate to automatically create pull requests for digest updates. Renovate will:
- Check daily for new image digest versions
- Auto-merge digest-only updates (backward compatible)
- Create PRs for minor and major version updates (require manual review)
- Run on Monday mornings (before 3am UTC) to avoid disrupting development
If you need to manually update a base image version:
-
Identify the new image tag you want to use (e.g.,
node:20-alpine) -
Find the digest by running:
docker pull node:20-alpine docker inspect node:20-alpine | grep DigestOr check Docker Hub for the specific image.
-
Update the Dockerfile:
FROM node:20-alpine@sha256:<paste-the-digest-here> -
Create a pull request with changes to the affected Dockerfile(s)
-
Include reasoning in the PR description (e.g., security patches, feature requirements)
- Renovate Config: renovate.json
- Configures which images Renovate monitors
- Sets auto-merge policies
- Defines update schedules
- Never use untagged images (
FROM pythonis not allowed) - Always include a digest (
FROM python:3.11-slim@sha256:...) - Use specific version tags (e.g.,
node:18.18.2-alpinerather thannode:18-alpine) - Document significant image updates in commit messages and PRs
- Keep images updated but review major changes carefully
Problem: Build fails with "image not found" after pinning
- Solution: Verify the digest is correct by pulling the image manually
Problem: Different digest values on different machines
- Solution: This is expected - use the digest from your pinned FROM statement, not local system
Problem: Renovate is not creating PRs
- Solution: Check
renovate.jsonconfiguration and ensure Renovate app is installed on the repository
If you have questions about contributing, please open an issue or reach out to the maintainers.