Skip to content

Development Setup & Contributing

Welcome to the Ascend project! We’re excited to have you contribute. This guide will help you set up your development environment and understand our contribution workflow.

  1. Project Structure
  2. Development Environment Setup
  3. Building from Source
  4. Running Tests
  5. Code Style and Standards
  6. Contributing Guidelines
  7. Pull Request Process
  8. Community Guidelines

Ascend is organized as a multiple micro services. You can find project structure of each service below.:

ascend/
├── testlab/ # Backend Experiment server (Java/Vert.x)
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/ # Java source code
│ │ │ │ └── com/ascend/testlab/
│ │ │ │ ├── allocation/ # Assignment logic
│ │ │ │ ├── client/ # Database & cache clients
│ │ │ │ ├── config/ # Configuration
│ │ │ │ ├── dao/ # Data access layer
│ │ │ │ ├── dto/ # Request/Response objects
│ │ │ │ ├── entity/ # Domain models
│ │ │ │ ├── rest/ # REST endpoints
│ │ │ │ ├── service/ # Business logic
│ │ │ │ └── verticle/ # Vert.x verticles
│ │ │ └── resources/
│ │ │ ├── config/ # Application configs
│ │ │ ├── db/ # Database schemas
│ │ │ └── webroot/ # Static files & Swagger
│ │ └── test/ # Unit & integration tests
│ ├── pom.xml # Maven configuration
│ ├── Dockerfile # Docker build
│ └── docker-compose.yaml # Local dev setup
├── flockr/ # Backend Audience Engine (Java/Vert.x)
│ ├── env.docker # Docker environment template
│ ├── Makefile # Build & deployment automation
│ ├── DOCKER.md # Docker documentation
│ ├── README.md
│ │
│ ├── flockr-admin/ # Admin service module
│ │ ├── pom.xml
│ │ ├── Dockerfile
│ │ └── src/
│ │ ├── main/
│ │ │ ├── java/io/ascend/flockr/admin/
│ │ │ │ ├── client/ # External clients (Postgres, Flink, WebClient)
│ │ │ │ ├── config/ # Configuration classes
│ │ │ │ ├── constants/ # Application constants
│ │ │ │ ├── domain/ # Domain models
│ │ │ │ ├── exception/ # Custom exceptions
│ │ │ │ ├── injection/ # Guice modules and injector
│ │ │ │ ├── io/ # Request/Response DTOs
│ │ │ │ ├── provider/ # JAX-RS providers
│ │ │ │ ├── repository/ # Data access layer (PostgreSQL)
│ │ │ │ ├── rest/ # REST controllers
│ │ │ │ ├── service/ # Business logic services
│ │ │ │ ├── util/ # Utilities
│ │ │ │ ├── validation/ # Custom validators
│ │ │ │ ├── verticle/ # Vert.x verticles
│ │ │ │ └── MainLauncher.java
│ │ │ └── resources/
│ │ │ ├── config/ # HOCON configs
│ │ │ │ ├── application/
│ │ │ │ ├── postgres/
│ │ │ │ ├── flink/
│ │ │ │ ├── kafka-producer/
│ │ │ │ ├── http-server/
│ │ │ │ └── swagger/
│ │ │ ├── db/postgres/ # Database scripts
│ │ │ │ ├── 01_schema.sql
│ │ │ │ └── 02_seed.sql
│ │ │ ├── logback/ # Logging config
│ │ │ └── webroot/swagger/ # Swagger UI & spec
│ │ └── test/ # Unit & integration tests
│ │
│ ├── flockr-users/ # Users service module
│ │ ├── pom.xml
│ │ ├── Dockerfile
│ │ └── src/
│ │ ├── main/
│ │ │ ├── java/io/ascend/flockr/users/
│ │ │ │ ├── client/ # Aerospike client
│ │ │ │ ├── config/ # Config classes
│ │ │ │ ├── constants/ # Application constants
│ │ │ │ ├── controller/ # REST controllers
│ │ │ │ ├── dto/ # DTOs
│ │ │ │ ├── guice/ # Guice application context
│ │ │ │ ├── module/ # Guice modules
│ │ │ │ ├── service/ # Business logic
│ │ │ │ ├── verticle/ # Vert.x verticles
│ │ │ │ ├── AbstractMainApplication.java
│ │ │ │ └── MainApplication.java
│ │ │ └── resources/
│ │ │ ├── config/ # HOCON config
│ │ │ │ ├── aerospike/
│ │ │ │ ├── http-server/
│ │ │ │ └── swagger/
│ │ │ ├── logback/ # Logging config
│ │ │ └── webroot/swagger/ # Swagger UI & spec
│ │ └── test/
│ │
│ └── docker/
│ ├── docker-start.sh # Start all services
│ ├── docker-stop.sh # Stop all services
│ ├── docker-status.sh # Check service status
│ ├── docker-clean.sh # Clean containers/volumes
│ └── config/
│ ├── flink.conf
│ └── postgres.conf
├── ascend-astra/ # Gateway service
│ ├── Dockerfile
│ ├── docker-compose.yml
│ ├── plugins/
│ │ ├── conditional-req-termination/
│ │ ├── cors/
│ │ ├── maintenance/
│ │ ├── rate-limiting-v2/
│ │ ├── strip-headers/
│ │ └── swap-header/
│ ├── ascend-astra/
│ │ ├── kong.rockspec
│ │ └── kong.yml
│ └── scripts/
│ ├── docker-start.sh
│ ├── docker-stop.sh
│ ├── deck-dump.sh
│ ├── deck-sync.sh
│ └── setup.sh
├── ascend-panel/
│ ├── src/
│ │ ├── store/ # Redux store
│ │ │ ├── store.ts
│ │ │ ├── hooks.ts
│ │ │ └── slices/
│ │ │ └── counterSlice.ts
│ │ ├── theme/ # MUI theme
│ │ │ └── theme.ts
│ │ ├── App.tsx # Root component
│ │ ├── main.tsx # Entry point
│ │ └── index.css # Tailwind global styles
├── ascend-android-sdk/ # Android SDK (Kotlin)
│ ├── ascend-android/
│ │ └── src/
│ │ ├── main/java/com/ # SDK core
│ │ └── test/
│ ├── app/ # Example app
│ └── build.gradle.kts
├── ascend-ios/ # iOS SDK (Swift)
│ ├── Sources/
│ │ ├── Ascend/
│ │ ├── AscendCommon/
│ │ │ ├── AscendCore/
│ │ │ ├── AscendExperiments/
│ │ │ └── PluginSystem/
│ ├── Package.swift
│ └── Ascend.podspec
├── ascend-react-native-sdk/ # React Native SDK
│ ├── src/
│ ├── android/
│ ├── ios/
│ ├── example/
│ └── package.json
└── ascend/ # Documentation website
├── docs/
├── src/
│ ├── assets/
│ ├── content/
│ ├── pages/
│ ├── styles/
└── astro.config.js # Astro config
  • Allocation: Variant assignment logic with strategies and filters
  • DAO: Database access with query builders
  • Service: Business logic layer
  • REST: HTTP endpoints with OpenAPI specs
  • Client: PostgreSQL and Aerospike integrations
  • Admin: Flockr Admin service
  • DAO: Database access with query builders
  • Service: Business logic layer
  • REST: HTTP endpoints with OpenAPI specs
  • Client: PostgreSQL and Aerospike integrations
  • Plugins: Kong plugins
  • Kong-Proxy: Main API Gateway
  • Kong-Admin: Kong Administration
  • Kong-Manager: Kong GUI dashboard
  • Client: PostgreSQL and Redis integrations
  • App: Frontend Service
  • Network: HTTP client with retry logic
  • Plugins: Experiments and future features
  • Core: User management, device info, configuration
  • Network: HTTP client with retry logic
  • Storage: Local caching and persistence
  • Plugin Architecture: Modular, extensible design
  • AscendCore: Configuration, user management, device info
  • AscendExperiments: A/B testing functionality
  • AscendCommon: Shared utilities (logging, networking, storage)
  • TypeScript Layer: JavaScript API
  • Native Bridges: Android and iOS native modules
  • Type Definitions: Full TypeScript support

Ensure you have the following installed:

  • Java JDK 17 (Download)

    Terminal window
    java -version # Should show 17.x
  • Apache Maven 3.6+ (Download)

    Terminal window
    mvn -version
  • PostgreSQL 12+ (Download)

    Terminal window
    psql --version
  • Aerospike (optional, for caching) (Download)

  • Docker & Docker Compose (Download)

    Terminal window
    docker --version
    docker-compose --version
  • Android Studio (latest stable) (Download)
  • JDK 17
  • Android SDK (API 24+)
  • macOS (required for iOS development)
  • Xcode 12+ (Download)
  • Swift 5.0+
  • Node.js 16+ (Download)

    Terminal window
    node --version
  • Yarn (Download)

    Terminal window
    yarn --version
  • React Native CLI

    Terminal window
    npm install -g react-native-cli

Terminal window
git clone https://https://github.com/dream-horizon-org/testlab.git
cd testlab
Terminal window
# Create database
createdb experiment
# Run schema
psql -d experiment -f src/main/resources/db/postgresql/schema.sql

Create a .env file or export variables:

Terminal window
export PG_USER="postgres"
export PG_PASSWORD="your_password"
export ENV="local"
Terminal window
# Clean build
mvn clean install
# Skip tests (faster)
mvn clean install -DskipTests
# Build fat JAR
mvn clean package

Output: target/testlab/testlab-1.0-fat.jar

Option A: Using Maven

Terminal window
mvn exec:java

Option B: Using JAR

Terminal window
cd target/testlab
PG_USER=postgres PG_PASSWORD=your_password \
java -Dapp.environment=local \
-Dlogback.configurationFile=./resources/logback/logback.xml \
-jar testlab-1.0-fat.jar

Option C: Using IntelliJ IDEA

  1. Open testlab project in IntelliJ
  2. Create Run Configuration:
    • Type: Application
    • Main class: com.ascend.testlab.MainLauncher
    • VM options: -Dapp.environment=local -Dlogback.configurationFile=logback/logback-local.xml
    • Program arguments: run verticle.com.ascend.testlab.MainVerticle
    • Environment variables: ENV=local;PG_USER=postgres;PG_PASSWORD=your_password

Option D: Using Docker Compose

Terminal window
docker-compose up -d
Terminal window
curl http://localhost:8080/v1/health
Terminal window
git clone https://github.com/ascend/ascend-android-sdk.git
cd ascend-android-sdk
  • File → Open → Select ascend-android-sdk directory
  • Wait for Gradle sync to complete
Terminal window
# Command line
./gradlew build
# Or use Android Studio: Build → Make Project
Terminal window
./gradlew :app:installDebug
# Or use Android Studio: Run → Run 'app'
Terminal window
git clone https://github.com/ascend/ascend-ios.git
cd ascend-ios
Terminal window
swift build
Terminal window
swift test
Terminal window
open Package.swift
Terminal window
./build-framework.sh
Terminal window
git clone https://github.com/ascend/ascend-react-native-sdk.git
cd ascend-react-native-sdk
Terminal window
yarn install
Terminal window
yarn prepare

iOS:

Terminal window
cd example
yarn install
cd ios && pod install && cd ..
yarn ios

Android:

Terminal window
cd example
yarn install
yarn android

Terminal window
# Run all tests
mvn test
# Run integration tests
mvn verify
# Run specific test
mvn test -Dtest=AllocationServiceTest
# Generate coverage report
mvn jacoco:report
# Report at: target/site/jacoco/index.html
Terminal window
# Unit tests
./gradlew test
# Instrumented tests (requires emulator/device)
./gradlew connectedAndroidTest
# With coverage
./gradlew jacocoTestReport
Terminal window
# All tests
swift test
# Specific test
swift test --filter AscendExperimentsTests
Terminal window
# Unit tests
yarn test
# Type checking
yarn typecheck
# Linting
yarn lint

We use Google Java Format with Maven plugin.

Auto-format code:

Terminal window
mvn com.spotify.fmt:fmt-maven-plugin:format

Check formatting:

Terminal window
mvn com.spotify.fmt:fmt-maven-plugin:check

Style Guidelines:

  • 100 character line limit
  • 2 spaces for indentation
  • Use @Override annotations
  • Prefer final for variables when possible
  • Use meaningful variable names

Follow Kotlin Coding Conventions.

Key points:

  • 4 spaces for indentation
  • Use Kotlin idioms (data classes, extension functions)
  • Prefer val over var
  • Use meaningful names
  • Add KDoc comments for public APIs

Follow Swift API Design Guidelines.

Key points:

  • 4 spaces for indentation
  • Use clear, expressive names
  • Prefer value types (structs) over reference types
  • Use guard for early returns
  • Add documentation comments for public APIs

Follow Airbnb JavaScript Style Guide.

Auto-format:

Terminal window
yarn lint --fix

Key points:

  • 2 spaces for indentation
  • Use TypeScript strict mode
  • Prefer const over let
  • Use arrow functions
  • Add JSDoc comments for public APIs

  1. Check existing issues: Avoid duplicate work
  2. Discuss large changes: Open an issue first for major features
  3. Read the docs: Understand the architecture and patterns
Terminal window
# Fork on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/testlab.git
cd testlab
# Add upstream remote
git remote add upstream https://github.com/ascend/testlab.git
Terminal window
git checkout -b feature/your-feature-name
# or
git checkout -b fix/bug-description

Branch naming conventions:

  • feature/ - New features
  • fix/ - Bug fixes
  • docs/ - Documentation updates
  • refactor/ - Code refactoring
  • test/ - Test additions/fixes
  • Write clear, concise code
  • Follow code style guidelines
  • Add tests for new functionality
  • Update documentation

Follow Conventional Commits:

Terminal window
git commit -m "feat: add support for weighted cohorts"
git commit -m "fix: resolve race condition in allocation"
git commit -m "docs: update API documentation"
git commit -m "test: add tests for variant selection"

Commit message format:

<type>(<scope>): <subject>
<body>
<footer>

Types:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation
  • style: Formatting changes
  • refactor: Code restructuring
  • test: Adding/updating tests
  • chore: Maintenance tasks
Terminal window
git push origin feature/your-feature-name

Go to GitHub and create a Pull Request from your fork to the main repository.


Before submitting, ensure:

  • ✅ Code follows style guidelines
  • ✅ All tests pass
  • ✅ New tests added for new functionality
  • ✅ Documentation updated
  • ✅ No unnecessary dependencies added
  • ✅ Commit messages follow conventions
  • ✅ PR description is clear and complete
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
Describe how you tested your changes
## Checklist
- [ ] Code follows style guidelines
- [ ] Tests pass locally
- [ ] Added tests for new features
- [ ] Updated documentation
- [ ] No breaking changes (or documented)
## Related Issues
Closes #123
  1. Automated Checks: CI/CD runs tests and linters
  2. Code Review: Maintainers review your code
  3. Discussion: Address feedback and make changes
  4. Approval: Maintainer approves the PR
  5. Merge: PR is merged into main branch
  • Keep PRs small and focused
  • Write clear descriptions
  • Respond promptly to feedback
  • Be open to suggestions
  • Rebase on latest main if needed

We are committed to providing a welcoming and inclusive environment. Please:

  • Be respectful: Treat everyone with respect and kindness
  • Be inclusive: Welcome newcomers and diverse perspectives
  • Be collaborative: Work together towards common goals
  • Be constructive: Provide helpful feedback
  • Be professional: Keep discussions focused and productive
  • GitHub Issues: Bug reports and feature requests
  • GitHub Discussions: Questions and community discussions
  • Pull Requests: Code contributions
  • Security Issues: Email security@ascend-project.org
  • Documentation: Check our comprehensive docs first
  • Discussions: Ask questions in GitHub Discussions
  • Issues: Report bugs with detailed reproduction steps
  • Community: Connect with other contributors

For faster iteration, use Vert.x hot reload:

Terminal window
mvn compile vertx:run

When changing schema:

  1. Update schema.sql
  2. Create migration script (if needed)
  3. Test on fresh database
  4. Document changes

Enable debug logging:

Terminal window
java -Dlogback.configurationFile=logback-debug.xml -jar testlab-1.0-fat.jar

Android:

Terminal window
# Publish to local Maven
./gradlew publishToMavenLocal
# In your app's build.gradle
repositories {
mavenLocal()
}

iOS:

// Use local package in Xcode
// File → Add Package Dependencies → Add Local...

React Native:

Terminal window
# Link local package
cd example
yarn link ../

Problem: Maven build fails with missing dependencies

Solution:

Terminal window
mvn clean install -U # Force update dependencies

Problem: Gradle sync fails in Android Studio

Solution:

Terminal window
./gradlew --refresh-dependencies

Problem: Database tests fail

Solution: Ensure PostgreSQL is running and schema is initialized

Problem: Integration tests timeout

Solution: Increase timeout in test configuration


We follow Semantic Versioning:

  • Major (X.0.0): Breaking changes
  • Minor (x.X.0): New features (backward compatible)
  • Patch (x.x.X): Bug fixes
  1. Update version numbers
  2. Update CHANGELOG.md
  3. Create Git tag
  4. Build release artifacts
  5. Publish to package repositories
  6. Create GitHub release


Thank you for contributing to Ascend! Your contributions help make experimentation accessible to everyone.

Questions? Feel free to ask in GitHub Discussions or open an issue.

Happy coding! 🚀


Built with ❤️ by the Ascend community