diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..edcf6ad --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,66 @@ +FROM mcr.microsoft.com/devcontainers/java:dev-25 + +ARG MAVEN_VERSION=3.9.9 +ARG MAVEN_BASE_URL=https://archive.apache.org/dist/maven/maven-3 + +# Use native TLS so uv respects the system CA bundle (required for corporate proxies) +ENV UV_NATIVE_TLS=1 + +# Copy corporate CA certificates from host for build-time HTTPS trust. +# These are populated by init-certs.sh (initializeCommand) on the host. +COPY local-certs/ /usr/local/share/ca-certificates/ + +# Install tools that were previously provided through Dev Container features: +# Docker-in-Docker dependencies, Docker CLI/Compose/Buildx, GitHub CLI, +# and Python tooling (uv + pre-commit). +RUN set -e; \ + \ + update-ca-certificates; \ + \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + apt-transport-https \ + ca-certificates \ + curl \ + dirmngr \ + git \ + gnupg2 \ + iptables \ + jq \ + lsb-release \ + pigz \ + python3-pip \ + python3-venv \ + sudo \ + wget; \ + \ + install -m 0755 -d /etc/apt/keyrings; \ + curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg; \ + chmod a+r /etc/apt/keyrings/docker.gpg; \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian trixie stable" > /etc/apt/sources.list.d/docker.list; \ + \ + curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /etc/apt/keyrings/githubcli-archive-keyring.gpg; \ + chmod a+r /etc/apt/keyrings/githubcli-archive-keyring.gpg; \ + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list; \ + \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + containerd.io \ + docker-buildx-plugin \ + docker-ce \ + docker-ce-cli \ + docker-compose-plugin \ + gh; \ + mkdir -p /opt; \ + wget -q "${MAVEN_BASE_URL}/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" -O /tmp/maven.tar.gz; \ + tar -xzf /tmp/maven.tar.gz -C /opt; \ + ln -sf "/opt/apache-maven-${MAVEN_VERSION}/bin/mvn" /usr/local/bin/mvn; \ + rm /tmp/maven.tar.gz; \ + mvn -version; \ + \ + python3 -m pip install --no-cache-dir --break-system-packages uv pre-commit; \ + uv python install 3.14; \ + usermod -aG docker vscode; \ + apt-mark hold docker-ce docker-ce-cli; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..75b7b22 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,51 @@ +{ + "name": "Decathlon Internal Developer Platform", + "build": { + "dockerfile": "Dockerfile", + "context": "." + }, + + "customizations": { + "vscode": { + "extensions": [ + "vscjava.vscode-java-pack", + "vmware.vscode-spring-boot", + "vscjava.vscode-lombok", + "bruno-api-client.bruno", + "yzhang.markdown-all-in-one", + "bierner.markdown-mermaid", + "redhat.vscode-yaml" + ] + } + }, + + "forwardPorts": [8084, 5437, 8000], + + "runArgs": ["--privileged"], + + "mounts": [ + "source=idp-core-maven-cache,target=/home/vscode/.m2,type=volume" + ], + + "initializeCommand": "bash .devcontainer/init-certs.sh || true", + "portsAttributes": { + "8000": { + "label": "Documentation Site", + "onAutoForward": "notify" + }, + "8084": { + "label": "IDP Application", + "onAutoForward": "notify" + }, + "5437": { + "label": "PostgreSQL Database", + "onAutoForward": "silent" + } + }, + + "onCreateCommand": "sudo mkdir -p /home/vscode/.m2 && sudo chown -R vscode:vscode /home/vscode/.m2", + "postCreateCommand": "cd docs && uv sync", + "postStartCommand": "bash -lc 'if ! docker info >/dev/null 2>&1; then sudo mkdir -p /var/run /var/lib/docker && sudo nohup dockerd >/tmp/dockerd.log 2>&1 & fi; for i in $(seq 1 30); do docker info >/dev/null 2>&1 && break; sleep 1; done; docker compose up -d'", + + "remoteUser": "vscode" +} diff --git a/.devcontainer/init-certs.sh b/.devcontainer/init-certs.sh new file mode 100755 index 0000000..0873376 --- /dev/null +++ b/.devcontainer/init-certs.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Runs on the HOST before container creation (initializeCommand). +# On Linux hosts with corporate SSL inspection, copies host CA certificates +# into .devcontainer/local-certs/ so they can be bind-mounted into the container. +# On macOS/Windows or hosts without those paths, this is a no-op. + +CERT_DIR="$(cd "$(dirname "$0")" && pwd)/local-certs" +mkdir -p "$CERT_DIR" + +if [ -f "/etc/ssl/certs/ca-certificates.crt" ]; then + cp "/etc/ssl/certs/ca-certificates.crt" "$CERT_DIR/" +fi + +if [ -d "/usr/local/share/ca-certificates" ]; then + find /usr/local/share/ca-certificates -maxdepth 2 -name "*.crt" \ + -exec cp {} "$CERT_DIR/" \; 2>/dev/null || true +fi diff --git a/.devcontainer/install-certs.sh b/.devcontainer/install-certs.sh new file mode 100755 index 0000000..4b77c5b --- /dev/null +++ b/.devcontainer/install-certs.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Runs inside the container during onCreateCommand. +# Installs host CA certificates (populated by init-certs.sh) into the +# container's system trust store. If no host certs were provided, this is a no-op. + +CERT_SOURCE="/tmp/host-certs" + +if [ -z "$(ls -A "$CERT_SOURCE" 2>/dev/null)" ]; then + echo "No host certificates found in $CERT_SOURCE, skipping." + exit 0 +fi + +echo "Installing host CA certificates into container trust store..." +sudo cp -rp "$CERT_SOURCE"/. /usr/local/share/ca-certificates/ +sudo update-ca-certificates diff --git a/.devcontainer/local-certs/.gitkeep b/.devcontainer/local-certs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ea541b4..c0a1dd0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -20,7 +20,7 @@ updates: pull-request-branch-name: separator: "-" - # Docker dependencies + # Root Docker dependencies - package-ecosystem: "docker" directory: "/" schedule: @@ -30,6 +30,16 @@ updates: pull-request-branch-name: separator: "-" + # Devcontainer Docker dependencies + - package-ecosystem: "docker" + directory: "/.devcontainer" + schedule: + interval: "daily" + time: "05:00" + open-pull-requests-limit: 5 + pull-request-branch-name: + separator: "-" + # GitHub Actions dependencies - package-ecosystem: "github-actions" directory: "/" diff --git a/.gitignore b/.gitignore index 04557c3..e7cd9be 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,13 @@ mvnw.cmd .env application-secret.* +### DevContainer ### +# Host certificates copied by .devcontainer/init-certs.sh — never commit cert files +.devcontainer/local-certs/* +!.devcontainer/local-certs/.gitkeep + +### Node.js ### +**/node_modules/ # BlueJ files *.ctxt diff --git a/.vale/styles/config/vocabularies/IDP/accept.txt b/.vale/styles/config/vocabularies/IDP/accept.txt index f4bc6a5..d7c6af9 100644 --- a/.vale/styles/config/vocabularies/IDP/accept.txt +++ b/.vale/styles/config/vocabularies/IDP/accept.txt @@ -38,3 +38,4 @@ ADRs npm Docusaurus markdownlint +devcontainer diff --git a/Dockerfile b/Dockerfile index 7dd4bd0..c2aa883 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM eclipse-temurin:25-jre-alpine +FROM eclipse-temurin:25-jre-alpine@sha256:f10d6259d0798c1e12179b6bf3b63cea0d6843f7b09c9f9c9c422c50e44379ec ENV PORT=8080 diff --git a/docker-compose.yml b/docker-compose.yml index be4859d..5786781 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,10 @@ --- -version: "3.8" - services: postgres: - image: postgres:14 + image: postgres:18 environment: POSTGRES_USER: idpcore - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-idpcore_password} + POSTGRES_PASSWORD: idpcore_password ports: - "5437:5432" networks: diff --git a/docs/src/contributing/development-setup.md b/docs/src/contributing/development-setup.md index 5839e2c..80af42a 100644 --- a/docs/src/contributing/development-setup.md +++ b/docs/src/contributing/development-setup.md @@ -1,29 +1,15 @@ --- title: Development Setup -description: Set up your local development environment for IDP-Core +description: Set up your local development environment for the Internal Developer Platform --- -This guide walks you through setting up a complete development environment for IDP-Core. +This guide focuses on using the devcontainer so you don’t need local Java/Maven setup. ## Prerequisites -| Tool | Version | Purpose | -| ------ | ------- | --------------- | -| Java | 25+ | Runtime | -| Maven | 3.9+ | Build tool | -| Docker | 20.10+ | Local services | -| Git | 2.30+ | Version control | -| IDE | - | Development | - -### Verify Installation - -```bash -java -version # Should show 25+ -mvn -version # Should show 3.9+ -docker --version -git --version -pre-commit --version # If using pre-commit (recommended) -``` +- Docker 20.10+ +- Git 2.30+ +- VS Code (recommended) or JetBrains IntelliJ IDEA --- @@ -35,36 +21,44 @@ git clone https://github.com/YOUR_USERNAME/internal-developer-platform.git cd internal-developer-platform # Add upstream remote -git remote add upstream https://github.com/Decathlon/internal-developer-platform.git +git remote add upstream https://github.com/decathlon/internal-developer-platform.git ``` --- -## IDE Setup +## Devcontainer Setup + +The devcontainer provides Java 25, Maven 3.9.9, Docker command-line tool, and recommended IDE extensions. -### VS Code (Recommended) +### VS Code -1. Install [VS Code](https://code.visualstudio.com/) -2. Install extensions: - - Java Extension Pack - - Maven for Java - - Docker -3. Open the project folder in VS Code -4. Import Maven projects when prompted +1. Install [VS Code](https://code.visualstudio.com/) and the **DevContainers** extension +2. Ensure Docker is running +3. Open the project folder +4. Select **Reopen in Container** (or run **DevContainers: Reopen in Container**) +5. Wait for the container build and Maven import + +### JetBrains IDEs + +1. Ensure Docker is running +2. Open the project folder +3. Choose **DevContainer** / **Open in DevContainer** +4. Wait for the container build and Maven import --- ## Start the project -For your development setup, you can refer to the Getting started documentation here: [Getting Started](getting-started.md) +Once the devcontainer is running, you have a fully set up environment. At startup, the `docker compose up` command will run the PostgreSQL database. As well, in the `docs` folder, the `uv` virtual environment is already set up. -### Pre-Commit Hooks (Optional) +### Included Tools -Install pre-commit hooks for code quality: +The devcontainer includes: -```bash -pre-commit install -``` +- Pre-commit tool (run `pre-commit install` to enable hooks) +- GH command-line tool +- Python with UV and utilities for docs site generation +- PostgreSQL database running with `docker compose` --- @@ -94,6 +88,8 @@ src/main/resources/db/local/ ### Reset Database +Within the devcontainer, you can reset the database with: + ```bash # Drop and recreate docker compose down -v @@ -143,7 +139,7 @@ pre-commit run --all-files ```bash git add . -git commit -m "feat: add my feature" +git commit -m "feat(scope): add my feature" ``` ### 6. Push & Create PR diff --git a/docs/src/deployment/docker.md b/docs/src/deployment/docker.md index e6254a3..8d8e67d 100644 --- a/docs/src/deployment/docker.md +++ b/docs/src/deployment/docker.md @@ -73,7 +73,7 @@ services: retries: 3 postgres: - image: postgres:14-alpine + image: postgres:18-alpine environment: - POSTGRES_DB=idp - POSTGRES_USER=idp @@ -134,7 +134,7 @@ docker run -d \ -e POSTGRES_DB=idp \ -e POSTGRES_USER=idp \ -e POSTGRES_PASSWORD=idp \ - postgres:14-alpine + postgres:18-alpine # Run IDP-Core docker run -d \ @@ -163,10 +163,10 @@ Then build and run the Docker image: ```bash # Build -docker build -t internal-developer-platform:local . +docker build -t idp:local . # Run -docker run -d -p 8080:8080 internal-developer-platform:local +docker run -d -p 8080:8080 idp:local ``` ### Multi-stage Build diff --git a/docs/src/getting-started/installation.md b/docs/src/getting-started/installation.md index 6031df0..efb5f35 100644 --- a/docs/src/getting-started/installation.md +++ b/docs/src/getting-started/installation.md @@ -7,9 +7,9 @@ This guide covers multiple ways to install and run the Internal Developer Platfo --- -## Using Docker (standard method) +## Using Maven (standard method) -The recommended way to get started with the Internal Developer Platform is using Docker and Docker Compose. +The recommended way to get started with the Internal Developer Platform is using Maven. 1. **Clone the Repository** @@ -26,12 +26,10 @@ The recommended way to get started with the Internal Developer Platform is using 3. **Run the Internal Developer Platform Application** - Once the database runs, start the Internal Developer Platform app by building and running it with Docker: + Once the database runs, start the Internal Developer Platform app by building and running it with Maven: ```bash - mvn clean package -DskipTests - docker build -t idp-core . - docker run -p 8084:8084 --env SPRING_PROFILES_ACTIVE=local idp-core + mvn spring-boot:run -Dspring-boot.run.profiles=local,secret ``` The app will be accessible at `http://localhost:8084`. In particular, the OpenAPI documentation will be available at `http://localhost:8084/swagger-ui.html`.