βοΈπ» Building a Local Development, Testing & Deployment Environment
A well-structured local development environment is essential for improving code quality, automating testing, and streamlining deployments.
In this guide, we will progressively build a local ecosystem for developers, adding essential tools step by step. The final goal is to create an environment that allows you to write, analyze, test, and deploy code efficiently.
This article serves as the central hub of the series β each tool (e.g., SonarQube, ArgoCD, Monitoring) will have its own dedicated post with installation details, while here weβll explain how everything integrates together.
π Planned Components
- π Code Analysis (SonarQube) β Static code analysis for code quality.
- π Linting (SonarLint for IDEs) β Consistent coding standards in real-time.
- π Version Control (GitHub) β Branches, PRs, tags, semantic versioning (weβll link a dedicated article).
- β‘ CI/CD Pipelines (GitHub Actions) β Automated build & test pipelines.
- π Deployment (ArgoCD) β GitOps-based application delivery.
- π Monitoring (Prometheus, Grafana) β Observability for apps.
π Project Structure
Hereβs the proposed folder layout for our environment:
local-dev-environment/
β
βββ sonarqube/ # SonarQube setup and configuration
β βββ conf/ # SonarQube config (sonar.properties, etc.)
β βββ data/ # Persistent data storage
β βββ logs/ # Log files
β βββ extensions/ # Plugins & extensions
β
βββ code-examples/ # Sample code for analysis & testing
β βββ python/
β βββ api-requests.py
β
βββ tests/ # Example unit tests
β βββ test_example.py
β
βββ .github/
β βββ workflows/
β β βββ sonarqube-analysis.yml # Pipeline
β βββ actions-runner/ # Self-hosted GitHub Actions Runner
β βββ run.sh # Script to start the runner
β
βββ docker-compose.yaml # Compose file for multiple services
βββ README.md # Project documentation
βββ requirements.txt # Dependencies
...
... (in development)
Steps
- Create the folders and initialize the repository
- You can initialize the repository by running git init in the root folder of local-dev-environment.
- Push the code to your GitHub repository and link it here: Project GitHub Repository
This guide will start with SonarQube, a powerful tool for static code analysis, and expand as we integrate more tools.
π Static Code Analysis with SonarQube
We start our environment with SonarQube, a powerful static analysis tool that detects bugs, security vulnerabilities, and code smells.
Once SonarQube is running locally (via docker-compose), we can integrate it into our pipeline so that every push to the repository gets analyzed automatically.
- π Detailed installation guide: SonarQube Setup Article
β‘ GitHub Actions β SonarQube Analysis Pipeline
As a first CI/CD integration, letβs configure a GitHub Actions workflow to run SonarQube scans on our code. This pipeline runs on the dev branch β a common branching strategy where:
- dev β integration branch for ongoing development
- main β stable production-ready branch
- feature/* β temporary branches for new features
Weβll create a separate article on branching models, semantic versioning, and release workflows (to keep this guide focused).
- π Detailed installation guide: Branching & Semantic Versioning Article
π§ Setting Up GitHub Actions
- Navigate to your repository on GitHub.
- Click on the Actions tab in the repository menu.
- If this is your first time, youβll be prompted to configure a new workflow. Click βSet up this workflow yourselfβ.
- GitHub will open a YAML editor where you can define your first workflow.
-
Inside your repository, make sure you have the following directory structure:
.github/ βββ workflows/ βββ sonarqube-analysis.yml
This file will contain the pipeline configuration for SonarQube analysis.
π Add SonarQube Token to GitHub Secrets
For the workflow to authenticate with SonarQube, you need a token:
- Generate a token in SonarQube:
- Go to My Account β Security β Generate Tokens.
- Copy the generated token (you will not be able to see it again).
- Add it to your GitHub repository secrets:
- Open your GitHub repository.
- Go to Settings β Secrets and variables β Actions.
- Click New repository secret.
- Name it SONAR_TOKEN and paste the value from SonarQube.
- Workflow File: .github/workflows/sonarqube-analysis.yml
name: SonarQube Analysis
on:
push:
branches:
- dev
# Uncomment below if you want to analyze PRs into main
# pull_request:
# branches:
# - main
jobs:
sonarQube:
runs-on: self-hosted
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run SonarScanner
run: |
sonar-scanner \
-Dsonar.projectKey=chronos-desktop-app \
-Dsonar.sources=. \
-Dsonar.host.url=http://localhost:9001 \
-Dsonar.login=$
π₯οΈ Setting Up the Actions Runner
Since weβre running SonarQube locally, the pipeline needs a self-hosted GitHub Actions runner.
Steps to Add Actions Runner
- Create the folder:
mkdir -p .github/actions-runner
- Inside, add the script run.sh:
#!/bin/bash
cd .github/actions-runner
./run.sh
# Make it executable:
chmod +x .github/actions-runner/run.sh
# Start the runner before pushing code:
./github/actions-runner/run.sh
β οΈ Important Notes
β SonarQube must be running β Since we deployed it via Docker Compose, containers will auto-restart after a reboot (unless stopped manually in Docker Desktop). You can always check in Docker Desktop or via docker ps.
β Start the runner before committing/pushing β If the runner isnβt running, GitHub wonβt detect the workflow and the pipeline wonβt execute.
β Branch strategy β For now, we trigger analysis only on dev. Later, weβll extend this to main and release workflows.
π Key Points
- runs-on: self-hosted β The job runs on a self-hosted runner (needed since we use local SonarQube).
- SONAR_TOKEN β Stored in GitHub Secrets, generated from SonarQube.
- Branching strategy β For now, we run scans on dev. Later, we may extend it to main or PRs.
This ensures every code change on dev is scanned, keeping quality checks aligned with our development workflow.
π Next Steps
- Expand pipelines to include tests, builds, and deployments.
- Add ArgoCD to migrate and manage SonarQube in Kubernetes.
- Extend analysis pipelines for main branch with semantic versioning & release tags.
- Integrate monitoring to visualize the health of our apps.
This is just the first building block of our developer ecosystem. With each article, weβll add another piece until the full puzzle comes together. π§©