Implement CI/CD Pipeline and Ansible Deployment (Issue #14)

- Add GitHub Actions workflow for Docker build & push to private registry
- Add Gitea Actions workflow (compatible with GitHub Actions)
- Extend README.md with comprehensive Ansible role example:
  - Complete directory structure and file examples
  - Docker Compose template with health checks
  - Variable configuration for different environments
  - Vault integration for secure credential management
  - Deployment playbook and execution examples
- Add .dockerignore for optimized Docker builds
- Both workflows support workflow_dispatch with optional tag suffix
- Multi-platform builds (linux/amd64, linux/arm64)
- Smart caching and detailed build summaries
This commit is contained in:
GitHub Copilot committed 2025-09-01 17:35:26 +00:00
1 parent 8e0c13ae17
commit 239081364a
4 files changed
+398

No files matched your search

+51
View File
@@ -0,0 +1,51 @@
# Git
.git
.gitignore
.gitea
.github
# Python
__pycache__
*.pyc
*.pyo
*.pyd
.Python
*.so
.pytest_cache
.coverage
*.coverage
htmlcov/
.venv
venv/
env/
# IDE
.vscode
.idea
*.swp
*.swo
# Documentation
*.md
!README.md
# Test files
test.db
*.db-journal
# CI/CD
.github/
.gitea/
# Development
.devcontainer/
.env
.env.local
# Logs
*.log
logs/
# OS
.DS_Store
Thumbs.db
+67
View File
@@ -0,0 +1,67 @@
name: Build and Push Docker Image (Gitea)
on:
workflow_dispatch:
inputs:
tag_suffix:
description: 'Optional tag suffix (e.g., -dev, -staging)'
required: false
default: ''
env:
IMAGE_NAME: rs-sim-autostore
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Private Registry
uses: docker/login-action@v3
with:
registry: ${{ secrets.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Extract metadata
id: meta
run: |
echo "short_sha=${GITHUB_SHA::8}" >> $GITHUB_OUTPUT
echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
echo "timestamp=$(date +%Y%m%d-%H%M%S)" >> $GITHUB_OUTPUT
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
platforms: linux/amd64,linux/arm64
tags: |
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:latest${{ inputs.tag_suffix }}
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.short_sha }}${{ inputs.tag_suffix }}
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.branch }}-${{ steps.meta.outputs.timestamp }}${{ inputs.tag_suffix }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Image digest
run: echo "Image pushed with digest ${{ steps.docker_build.outputs.digest }}"
- name: Summary
run: |
echo "## Build Summary 🐳"
echo ""
echo "**Image:** ${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}"
echo "**Tags:**"
echo "- latest${{ inputs.tag_suffix }}"
echo "- ${{ steps.meta.outputs.short_sha }}${{ inputs.tag_suffix }}"
echo "- ${{ steps.meta.outputs.branch }}-${{ steps.meta.outputs.timestamp }}${{ inputs.tag_suffix }}"
echo ""
echo "**Commit:** ${{ github.sha }}"
echo "**Branch:** ${{ steps.meta.outputs.branch }}"
+67
View File
@@ -0,0 +1,67 @@
name: Build and Push Docker Image
on:
workflow_dispatch:
inputs:
tag_suffix:
description: 'Optional tag suffix (e.g., -dev, -staging)'
required: false
default: ''
env:
IMAGE_NAME: rs-sim-autostore
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Private Registry
uses: docker/login-action@v3
with:
registry: ${{ secrets.REGISTRY_URL }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Extract metadata
id: meta
run: |
echo "short_sha=${GITHUB_SHA::8}" >> $GITHUB_OUTPUT
echo "branch=${GITHUB_REF#refs/heads/}" >> $GITHUB_OUTPUT
echo "timestamp=$(date +%Y%m%d-%H%M%S)" >> $GITHUB_OUTPUT
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
platforms: linux/amd64,linux/arm64
tags: |
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:latest${{ github.event.inputs.tag_suffix }}
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.short_sha }}${{ github.event.inputs.tag_suffix }}
${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.branch }}-${{ steps.meta.outputs.timestamp }}${{ github.event.inputs.tag_suffix }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Image digest
run: echo "Image pushed with digest ${{ steps.docker_build.outputs.digest }}"
- name: Summary
run: |
echo "## Build Summary 🐳" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Image:** \`${{ secrets.REGISTRY_URL }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Tags:**" >> $GITHUB_STEP_SUMMARY
echo "- \`latest${{ github.event.inputs.tag_suffix }}\`" >> $GITHUB_STEP_SUMMARY
echo "- \`${{ steps.meta.outputs.short_sha }}${{ github.event.inputs.tag_suffix }}\`" >> $GITHUB_STEP_SUMMARY
echo "- \`${{ steps.meta.outputs.branch }}-${{ steps.meta.outputs.timestamp }}${{ github.event.inputs.tag_suffix }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Commit:** \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "**Branch:** \`${{ steps.meta.outputs.branch }}\`" >> $GITHUB_STEP_SUMMARY
+213
View File
@@ -31,5 +31,218 @@ Dieses Projekt ist ein Simulator für das Logistiksystem "AutoStore", entwickelt
3. Wenn du dazu aufgefordert wirst, klicke auf **"Reopen in Container"**. VS Code wird die Entwicklungsumgebung automatisch aufsetzen.
4. Nach dem Start des Containers kann die Anwendung ausgeführt werden.
## 🐳 Container Deployment
### Docker Image Build & Push
Das Projekt enthält CI/CD Workflows für GitHub und Gitea Actions:
- **GitHub:** `.github/workflows/docker-build-push.yml`
- **Gitea:** `.gitea/workflows/docker-build-push.yml`
**Benötigte Secrets:**
- `REGISTRY_URL` - URL der privaten Container Registry
- `REGISTRY_USER` - Benutzername für Registry-Zugriff
- `REGISTRY_PASSWORD` - Passwort für Registry-Zugriff
**Ausführung:**
```bash
# Manuell über GitHub/Gitea UI (workflow_dispatch)
# oder über CLI (GitHub):
gh workflow run docker-build-push.yml
```
### Ansible Deployment
Beispiel einer Ansible-Rolle für das Deployment:
#### Verzeichnisstruktur
```
roles/
autostore-simulator/
tasks/
main.yml
templates/
docker-compose.yml.j2
vars/
main.yml
defaults/
main.yml
```
#### `roles/autostore-simulator/defaults/main.yml`
```yaml
---
# Container Konfiguration
autostore_image: "{{ registry_url }}/rs-sim-autostore"
autostore_tag: "latest"
autostore_container_name: "autostore-simulator"
autostore_port: 8000
autostore_network: "autostore-net"
# Registry Konfiguration
registry_url: "registry.example.com"
registry_user: "deployment"
registry_password: "{{ vault_registry_password }}"
# Datenbank Konfiguration
autostore_db_file: "/app/data/autostore.db"
autostore_data_volume: "autostore-data"
# Systemkonfiguration
autostore_restart_policy: "unless-stopped"
autostore_log_driver: "json-file"
autostore_log_max_size: "10m"
autostore_log_max_file: "3"
```
#### `roles/autostore-simulator/vars/main.yml`
```yaml
---
# Interne Variablen
autostore_full_image: "{{ autostore_image }}:{{ autostore_tag }}"
autostore_compose_file: "/opt/autostore/docker-compose.yml"
autostore_app_dir: "/opt/autostore"
```
#### `roles/autostore-simulator/tasks/main.yml`
```yaml
---
- name: Create AutoStore application directory
file:
path: "{{ autostore_app_dir }}"
state: directory
mode: '0755'
owner: root
group: root
- name: Create AutoStore data volume
docker_volume:
name: "{{ autostore_data_volume }}"
state: present
- name: Create AutoStore network
docker_network:
name: "{{ autostore_network }}"
state: present
- name: Login to container registry
docker_login:
registry_url: "{{ registry_url }}"
username: "{{ registry_user }}"
password: "{{ registry_password }}"
when: registry_url is defined
- name: Pull AutoStore image
docker_image:
name: "{{ autostore_full_image }}"
source: pull
force_source: yes
- name: Generate docker-compose.yml
template:
src: docker-compose.yml.j2
dest: "{{ autostore_compose_file }}"
mode: '0644'
notify: restart autostore
- name: Start AutoStore service
docker_compose:
project_src: "{{ autostore_app_dir }}"
state: present
recreate: smart
- name: Wait for AutoStore to be ready
uri:
url: "http://localhost:{{ autostore_port }}/health"
method: GET
status_code: 200
register: autostore_health
until: autostore_health.status == 200
retries: 30
delay: 2
```
#### `roles/autostore-simulator/templates/docker-compose.yml.j2`
```yaml
version: '3.8'
services:
autostore-simulator:
image: {{ autostore_full_image }}
container_name: {{ autostore_container_name }}
restart: {{ autostore_restart_policy }}
ports:
- "{{ autostore_port }}:8000"
volumes:
- {{ autostore_data_volume }}:/app/data
environment:
- DATABASE_URL=sqlite:///{{ autostore_db_file }}
networks:
- {{ autostore_network }}
logging:
driver: "{{ autostore_log_driver }}"
options:
max-size: "{{ autostore_log_max_size }}"
max-file: "{{ autostore_log_max_file }}"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
volumes:
{{ autostore_data_volume }}:
external: true
networks:
{{ autostore_network }}:
external: true
```
#### `roles/autostore-simulator/handlers/main.yml`
```yaml
---
- name: restart autostore
docker_compose:
project_src: "{{ autostore_app_dir }}"
restarted: yes
```
#### Playbook Beispiel
```yaml
---
- hosts: autostore_servers
become: yes
vars:
registry_url: "my-registry.example.com"
autostore_tag: "v1.0.0"
vault_registry_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
66633...encrypted...66633
roles:
- autostore-simulator
post_tasks:
- name: Verify AutoStore API is accessible
uri:
url: "http://{{ inventory_hostname }}:{{ autostore_port }}/health"
method: GET
delegate_to: localhost
```
#### Deployment ausführen
```bash
# Inventory und Vault-Passwort vorbereiten
ansible-playbook -i inventory/production autostore-deploy.yml --ask-vault-pass
# Mit spezifischem Tag
ansible-playbook -i inventory/production autostore-deploy.yml \
--ask-vault-pass \
-e "autostore_tag=latest"
```
---
*Dieses Projekt wurde mit Unterstützung von GitHub Copilot erstellt.*