feat(deploy): add Gitea registry publish script and pull-based compose

- scripts/publish.ps1: build image and push to git.azuze.fr/kawa/imptune
- docker-compose.yml: reference published image (build kept for local builds)
- docker-compose.override.yml: gitignored live-reload dev config
- add .gitignore (override + Python/data artifacts)
- README: document dev vs published-image run and publishing

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-11 17:21:07 +02:00
co-authored by Claude Opus 4.8
parent b2801eb757
commit 9e46fee312
4 changed files with 201 additions and 2 deletions
+17
View File
@@ -0,0 +1,17 @@
# Local dev compose overrides (personal / per-machine)
docker-compose.override.yml
# Python
__pycache__/
*.py[cod]
.pytest_cache/
.mypy_cache/
.ruff_cache/
*.egg-info/
.venv/
venv/
# Local data / build artifacts
/data/
imptune_data/
*.intunewin
+51
View File
@@ -1,3 +1,54 @@
# ImpTune
Build printer deploy packages (`.intunewin` for Intune, `.zip` for NinjaRMM) from Windows driver ZIPs via a web UI.
## Run
### Local development
```bash
docker compose up
```
`docker-compose.override.yml` is merged automatically: it mounts your working
copy into the container and runs uvicorn with `--reload`, so code edits are
picked up live. The override is gitignored (personal / per-machine).
### Run the published image
To run the image from the registry instead of building locally, skip the
override:
```bash
docker compose -f docker-compose.yml pull
docker compose -f docker-compose.yml up
```
Then open http://localhost:8000
## Publishing
`scripts/publish.ps1` builds the image and pushes it to the Gitea container
registry at `git.azuze.fr/kawa/imptune`.
```powershell
# build + push :<short-git-sha> and :latest (prompts for a Gitea token)
./scripts/publish.ps1
# tag an explicit version
./scripts/publish.ps1 -Tag v1.2.0
```
Use a Gitea access token (Settings → Applications, with package read/write
scope) as the password. For non-interactive runs set `GITEA_USER` /
`GITEA_TOKEN` env vars. Run `Get-Help ./scripts/publish.ps1 -Detailed` for all
parameters (`-Registry`, `-Owner`, `-Image`, `-NoBuild`, `-SkipLogin`, …).
## Environment variables
Set these under `environment:` in `docker-compose.yml`.
| Variable | Default | Purpose |
|------------|---------|--------------------------------------------------|
| `DATA_DIR` | `/data` | Storage root for the SQLite DB, drivers and icons. Should map to the `imptune_data` volume. |
| `PORT` | `8000` | Port the server listens on inside the container. |
+4 -1
View File
@@ -1,11 +1,14 @@
services:
imptune:
# Pull the published image by default (docker compose pull / up).
# `build` is kept so `docker compose build` still produces a correctly
# tagged local image; scripts/publish.ps1 pushes it to the registry.
image: git.azuze.fr/kawa/imptune:latest
build: .
ports:
- "8000:8000"
volumes:
- imptune_data:/data
- ./imptune:/app/imptune
restart: unless-stopped
environment:
- DATA_DIR=/data
+128
View File
@@ -0,0 +1,128 @@
#requires -Version 5.1
<#
.SYNOPSIS
Build the ImpTune container locally and push it to the Gitea container registry.
.DESCRIPTION
Builds the Docker image from the repo Dockerfile, tags it for the Gitea
registry (git.arescom.fr by default), logs in, and pushes one or more tags.
Login credentials are read, in order of precedence:
1. -Username / -Password parameters
2. $env:GITEA_USER / $env:GITEA_TOKEN
3. Interactive prompt (token is read as a SecureString)
Use a Gitea access token (Settings -> Applications) with package read/write
scope as the password — not your account password.
.EXAMPLE
./scripts/publish.ps1
Build and push :latest plus the short git SHA.
.EXAMPLE
./scripts/publish.ps1 -Tag v1.2.0
Build and push :v1.2.0 (and :latest unless -NoLatest).
.EXAMPLE
$env:GITEA_USER = "kawa"; $env:GITEA_TOKEN = "xxxx"; ./scripts/publish.ps1 -SkipLogin:$false
#>
[CmdletBinding()]
param(
# Registry host (Gitea instance).
[string]$Registry = "git.azuze.fr",
# Owner / organisation that holds the package.
[string]$Owner = "kawa",
# Image name.
[string]$Image = "imptune",
# Primary tag. Defaults to the short git SHA.
[string]$Tag,
# Also push :latest. On by default.
[switch]$NoLatest,
# Registry username. Falls back to $env:GITEA_USER then a prompt.
[string]$Username,
# Registry token/password. Falls back to $env:GITEA_TOKEN then a prompt.
[string]$Password,
# Skip the build step and only push existing local tags.
[switch]$NoBuild,
# Skip docker login (assume already authenticated).
[switch]$SkipLogin
)
$ErrorActionPreference = "Stop"
function Invoke-Checked {
param([Parameter(Mandatory)][string]$Exe, [Parameter(Mandatory)][string[]]$Args)
Write-Host " > $Exe $($Args -join ' ')" -ForegroundColor DarkGray
& $Exe @Args
if ($LASTEXITCODE -ne 0) {
throw "'$Exe $($Args -join ' ')' failed with exit code $LASTEXITCODE."
}
}
# Resolve repo root (parent of this script's folder) so the script works from anywhere.
$repoRoot = Split-Path -Parent $PSScriptRoot
Push-Location $repoRoot
try {
# --- Tag resolution -------------------------------------------------------
if (-not $Tag) {
try { $Tag = (git rev-parse --short HEAD).Trim() } catch { }
if (-not $Tag) { $Tag = "latest" }
}
$base = "$Registry/$Owner/$Image"
$tags = @("$base`:$Tag")
if (-not $NoLatest -and $Tag -ne "latest") { $tags += "$base`:latest" }
Write-Host "ImpTune container publish" -ForegroundColor Cyan
Write-Host " registry : $Registry"
Write-Host " image : $base"
Write-Host " tags : $($tags -join ', ')"
Write-Host ""
# --- Build ----------------------------------------------------------------
if (-not $NoBuild) {
Write-Host "Building image..." -ForegroundColor Cyan
$buildArgs = @("build")
foreach ($t in $tags) { $buildArgs += @("-t", $t) }
$buildArgs += "."
Invoke-Checked docker $buildArgs
Write-Host ""
}
# --- Login ----------------------------------------------------------------
if (-not $SkipLogin) {
if (-not $Username) { $Username = $env:GITEA_USER }
if (-not $Username) { $Username = Read-Host "Gitea username for $Registry" }
if (-not $Password) { $Password = $env:GITEA_TOKEN }
if (-not $Password) {
$secure = Read-Host "Gitea token/password for $Username" -AsSecureString
$Password = [System.Net.NetworkCredential]::new("", $secure).Password
}
Write-Host "Logging in to $Registry as $Username..." -ForegroundColor Cyan
# Pass the token via stdin so it never lands in process args or history.
$Password | docker login $Registry --username $Username --password-stdin
if ($LASTEXITCODE -ne 0) { throw "docker login failed (exit $LASTEXITCODE)." }
Write-Host ""
}
# --- Push -----------------------------------------------------------------
Write-Host "Pushing..." -ForegroundColor Cyan
foreach ($t in $tags) { Invoke-Checked docker @("push", $t) }
Write-Host ""
Write-Host "Done. Pushed:" -ForegroundColor Green
foreach ($t in $tags) { Write-Host " $t" -ForegroundColor Green }
}
finally {
Pop-Location
}