fix: Alpine compatibility + READMEs + roadmap

- setup-node: detect Alpine/Debian, use apk or NodeSource
- setup-aws: use pip on Alpine (musl), binary on Debian (glibc)
- setup-go: fix version parsing for Alpine (no grep -P)
- README per action with usage examples and input docs
- PLAN.md: roadmap for runner images, labels, Lambda dispatch
This commit is contained in:
2026-05-22 18:06:11 +01:00
parent 4be33e33f1
commit 1564c61acc
8 changed files with 206 additions and 12 deletions
+57
View File
@@ -0,0 +1,57 @@
# tinqs/ci — Roadmap
## Done (2026-05-22)
- [x] Create `tinqs/ci` repo on tinqs.com
- [x] Composite actions: checkout, setup-go, setup-node, setup-aws
- [x] Wire all 6 studio workflows to `tinqs/ci/*@v1`
- [x] Alpine + Debian compatibility in all actions
- [x] Runner image Dockerfiles: base, go, node, docker, deploy, godot
- [x] Architecture doc: `tinqs/internal/architecture/ci-runner-architecture.md`
## Next: Runner Images
Build and push purpose-built images to ECR. Each workflow type gets a lean image.
| Image | ECR name | Contents | Priority |
|-------|----------|----------|----------|
| base | tinqs-runner-base | Alpine + git + AWS CLI + SSH | High |
| go | tinqs-runner-go | base + Go 1.26 | High |
| node | tinqs-runner-node | base + Node 22 + pnpm | High |
| docker | tinqs-runner-docker | dind + Go + AWS CLI | High |
| deploy | tinqs-runner-deploy | base only | Medium |
| godot | tinqs-runner-godot | base + headless Godot 4.6 | Low (future) |
**Blocker:** No Docker on Forge, Lightsail unreachable. Options:
1. AWS CodeBuild project to build images from this repo
2. SSH to Lightsail when back online
3. Self-build: add a workflow here that builds images on the current runner
## Next: Label Routing
Once images exist:
1. Update ECS task definitions — one per image
2. Register runners with matching labels: `go`, `node`, `docker`, `deploy`
3. Update studio workflows: `runs-on: host` → specific labels
4. Lambda dispatcher (future): webhook → Fargate task with correct image
## Future: Lambda Dispatch + Cancel
Lambda code already exists in `tinqs-ltd/docs/lambda/` (ci-dispatch + ci-exec).
Move to `tinqs/studio/deploy/lambda/`, deploy with SAM.
- DynamoDB table for run tracking (`tinqs-ci-runs`)
- Cancel via `ecs:StopTask` on webhook or timeout
- EventBridge cron for stale task cleanup
- Deploy-only jobs run directly in Lambda (no Fargate needed)
See: `tinqs/internal/architecture/ci-runner-architecture.md`
## Future: More Actions
| Action | Purpose |
|--------|---------|
| `tinqs/ci/setup-python` | Python + pip/uv for ML pipelines |
| `tinqs/ci/deploy-ecs` | ECS update-service wrapper with wait |
| `tinqs/ci/deploy-s3` | S3 sync + CloudFront invalidation |
| `tinqs/ci/notify` | Post build status to Lobster GChat |
+33
View File
@@ -0,0 +1,33 @@
# tinqs/ci/checkout
Clones a repository from tinqs.com (self-hosted Gitea) using plain `git clone`.
Works on any runner with git installed — Alpine, Debian, or pre-baked images. No Node.js runtime, no GitHub API dependency.
## Usage
```yaml
- uses: tinqs/ci/checkout@v1
```
### With options
```yaml
- uses: tinqs/ci/checkout@v1
with:
repository: 'tinqs/engine' # default: current repo
ref: 'tinqs/main' # default: current branch
depth: '0' # default: 1 (shallow)
token: ${{ secrets.TOKEN }} # default: none (public clone)
path: 'engine' # default: . (current dir)
```
## Inputs
| Input | Default | Description |
|-------|---------|-------------|
| `repository` | `${{ github.repository }}` | Repository in `owner/repo` format |
| `ref` | `${{ github.ref_name }}` | Branch or tag |
| `depth` | `1` | Clone depth (0 = full history) |
| `path` | `.` | Directory to clone into |
| `token` | `` | Gitea access token for private repos |
+28
View File
@@ -0,0 +1,28 @@
# tinqs/ci/setup-aws
Installs AWS CLI and optionally logs into ECR.
Detects Alpine (musl) vs Debian (glibc) and uses the right install method — pip on Alpine, official binary on Debian. Credentials come from the runner environment (IAM task role on Fargate, instance profile on EC2).
## Usage
```yaml
- uses: tinqs/ci/setup-aws@v1
```
### With ECR login
```yaml
- uses: tinqs/ci/setup-aws@v1
with:
ecr-login: 'true'
ecr-repo: '149751500842.dkr.ecr.eu-west-1.amazonaws.com/tinqs-git'
```
## Inputs
| Input | Default | Description |
|-------|---------|-------------|
| `region` | `eu-west-1` | AWS region |
| `ecr-login` | `false` | Login to ECR after install |
| `ecr-repo` | `` | ECR repository URL (required when ecr-login is true) |
+15 -4
View File
@@ -1,5 +1,6 @@
# tinqs/ci/setup-aws — Tinqs Studio CI
# Installs AWS CLI and optionally logs into ECR.
# Detects Alpine (musl) vs Debian (glibc) and uses the right install method.
# Credentials come from the runner environment (IAM task role on Fargate, instance
# profile on EC2/Lightsail) — no explicit key configuration needed.
# Composite action — runs directly on the host.
@@ -30,10 +31,20 @@ runs:
# Install AWS CLI if missing
if ! command -v aws &>/dev/null; then
echo "Installing AWS CLI..."
curl -fsSL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o /tmp/awscli.zip
unzip -q /tmp/awscli.zip -d /tmp/aws-install
/tmp/aws-install/aws/install
rm -rf /tmp/awscli.zip /tmp/aws-install
if command -v apk &>/dev/null; then
# Alpine — use pip (AWS CLI v2 binary needs glibc)
apk add --no-cache python3 py3-pip
pip3 install --break-system-packages awscli 2>/dev/null || pip3 install awscli
elif command -v apt-get &>/dev/null; then
# Debian/Ubuntu — use official installer
apt-get update && apt-get install -y unzip curl
curl -fsSL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o /tmp/awscli.zip
unzip -q /tmp/awscli.zip -d /tmp/aws-install
/tmp/aws-install/aws/install
rm -rf /tmp/awscli.zip /tmp/aws-install
else
echo "ERROR: unsupported package manager" && exit 1
fi
fi
aws --version
+25
View File
@@ -0,0 +1,25 @@
# tinqs/ci/setup-go
Installs Go from go.dev and adds it to PATH.
Downloads the official tarball — works on any Linux (Alpine, Debian, etc.). Skips installation if the correct version is already present in the runner image.
## Usage
```yaml
- uses: tinqs/ci/setup-go@v1
```
### Specific version
```yaml
- uses: tinqs/ci/setup-go@v1
with:
go-version: '1.26.2'
```
## Inputs
| Input | Default | Description |
|-------|---------|-------------|
| `go-version` | `1.26.2` | Go version to install |
+3 -2
View File
@@ -1,11 +1,12 @@
# tinqs/ci/setup-go — Tinqs Studio CI
# Downloads Go from go.dev and adds it to PATH.
# Works on any Linux (Alpine, Debian, etc.) — just a tarball extract.
# Skips install if the correct version is already present (pre-baked runner image).
# Composite action — runs directly on the host.
# Author: Ozan + Claude Code — 2026-05-22
name: 'Tinqs Setup Go'
description: 'Install Go and configure PATH (replaces actions/setup-go)'
description: 'Install Go and configure PATH'
inputs:
go-version:
@@ -20,7 +21,7 @@ runs:
# Skip if already installed at correct version
if command -v go &>/dev/null; then
CURRENT=$(go version | grep -oP '\d+\.\d+\.\d+' || true)
CURRENT=$(go version | sed 's/.*go//' | cut -d' ' -f1)
if [ "$CURRENT" = "$GO_VERSION" ]; then
echo "Go $GO_VERSION already installed"
go version
+27
View File
@@ -0,0 +1,27 @@
# tinqs/ci/setup-node
Installs Node.js and optionally pnpm.
Detects Alpine vs Debian and uses the right package manager (`apk` or NodeSource). Skips installation if the correct major version is already present in the runner image.
## Usage
```yaml
- uses: tinqs/ci/setup-node@v1
```
### Options
```yaml
- uses: tinqs/ci/setup-node@v1
with:
node-version: '22' # default: 22
pnpm: 'true' # default: true
```
## Inputs
| Input | Default | Description |
|-------|---------|-------------|
| `node-version` | `22` | Node.js major version |
| `pnpm` | `true` | Install pnpm globally |
+18 -6
View File
@@ -1,11 +1,12 @@
# tinqs/ci/setup-node — Tinqs Studio CI
# Installs Node.js via NodeSource and optionally pnpm.
# Installs Node.js and optionally pnpm.
# Detects Alpine vs Debian and uses the right package manager.
# Skips install if the correct major version is already present (pre-baked runner image).
# Composite action — runs directly on the host.
# Author: Ozan + Claude Code — 2026-05-22
name: 'Tinqs Setup Node'
description: 'Install Node.js and pnpm (replaces actions/setup-node)'
description: 'Install Node.js and pnpm'
inputs:
node-version:
@@ -24,17 +25,28 @@ runs:
# Skip if already installed at correct major version
if command -v node &>/dev/null; then
CURRENT=$(node --version | grep -oP '\d+' | head -1)
CURRENT=$(node --version | sed 's/v//' | cut -d. -f1)
if [ "$CURRENT" = "$NODE_VERSION" ]; then
echo "Node $NODE_VERSION already installed"
node --version
[ "$INSTALL_PNPM" = "true" ] && command -v pnpm &>/dev/null && pnpm --version && exit 0
if [ "$INSTALL_PNPM" = "true" ] && command -v pnpm &>/dev/null; then
pnpm --version
exit 0
fi
fi
fi
echo "Installing Node.js $NODE_VERSION..."
curl -fsSL "https://deb.nodesource.com/setup_${NODE_VERSION}.x" | bash -
apt-get install -y nodejs
if command -v apk &>/dev/null; then
# Alpine
apk add --no-cache nodejs npm
elif command -v apt-get &>/dev/null; then
# Debian/Ubuntu
curl -fsSL "https://deb.nodesource.com/setup_${NODE_VERSION}.x" | bash -
apt-get install -y nodejs
else
echo "ERROR: unsupported package manager" && exit 1
fi
if [ "$INSTALL_PNPM" = "true" ]; then
npm install -g pnpm