diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..d96f33a --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,30 @@ +name: build + +on: + push: + branches: [main] + paths: + - 'images/**' + - '.gitea/workflows/build.yml' + schedule: + - cron: '0 4 * * 0' ## weekly sunday 04:00 UTC rebuild + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + container: + volumes: + - /var/run/docker.sock:/var/run/docker.sock + steps: + - uses: actions/checkout@v7 + - uses: docker/login-action@v3 + with: + registry: git.studiovita.li + username: ${{ gitea.actor }} + password: ${{ secrets.REGISTRY_TOKEN }} + - uses: docker/build-push-action@v6 + with: + context: images/act + push: true + tags: git.studiovita.li/studio/actions:ubuntu-latest diff --git a/images/act/Dockerfile b/images/act/Dockerfile new file mode 100644 index 0000000..5852605 --- /dev/null +++ b/images/act/Dockerfile @@ -0,0 +1,22 @@ +## renovate: datasource=docker depName=docker.gitea.com/runner-images +FROM docker.gitea.com/runner-images:ubuntu-latest@sha256:0e62e56b382ebf485bff1e51a05cbe27c708545a2e91425467fd31eb3e249521 + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends rsync; \ + rm -rf /var/lib/apt/lists/*; \ + rsync --version + +## renovate: datasource=github-releases depName=getsops/sops +ARG SOPS_VERSION=v3.13.3 + +RUN set -eux; \ + arch=$(dpkg --print-architecture); \ + asset="sops-${SOPS_VERSION}.linux.${arch}"; \ + url="https://github.com/getsops/sops/releases/download/${SOPS_VERSION}"; \ + curl -fsSL -o "/tmp/$asset" "$url/$asset"; \ + curl -fsSL -o /tmp/checksums.txt "$url/sops-${SOPS_VERSION}.checksums.txt"; \ + (cd /tmp && grep " ${asset}$" checksums.txt | sha256sum -c -); \ + install -m 0755 "/tmp/$asset" /usr/local/bin/sops; \ + rm -f "/tmp/$asset" /tmp/checksums.txt; \ + sops --version diff --git a/images/act/README.md b/images/act/README.md new file mode 100644 index 0000000..ab26281 --- /dev/null +++ b/images/act/README.md @@ -0,0 +1,5 @@ +# act runner image + +Gitea / Forgejo Actions runner image based on `runner-images:ubuntu-latest` with the pinned, checksum-verified SOPS build installed, plus `rsync` from apt. + +Built and pushed to `git.studiovita.li/studio/actions:ubuntu-latest` by the `build` workflow on push to `main`, weekly on a schedule (Sunday 04:00 cron), and on manual dispatch. The base image is pinned by digest so Renovate opens a PR whenever `runner-images:ubuntu-latest` changes; update `SOPS_VERSION` in `Dockerfile` to bump SOPS (both tracked in renovate.json). \ No newline at end of file diff --git a/renovate.json b/renovate.json index 8fe94d4..d1f00c2 100644 --- a/renovate.json +++ b/renovate.json @@ -13,6 +13,14 @@ "#+\\s*renovate:\\s*datasource=(?[^\\s]+)\\s+depName=(?[^\\s]+)\\s+[A-Z0-9_]+\\s*:\\s*[\"']?(?[^\\s\"'#]+)[\"']?" ], "description": "match any pinned dependency using SCREAMING_SNAKE_CASE naming as ENV" + }, + { + "customType": "regex", + "managerFilePatterns": ["**/Dockerfile"], + "matchStrings": [ + "#+\\s*renovate:\\s*datasource=(?[^\\s]+)\\s+depName=(?[^\\s]+)[ \\t]*\\n[ \\t]*ARG\\s+[A-Z0-9_]+=(?[^\\s\"'#]+)" + ], + "description": "match pinned ARG deps in Dockerfiles" } ] } diff --git a/sops/README.md b/sops/README.md index f11832e..56eda85 100644 --- a/sops/README.md +++ b/sops/README.md @@ -2,4 +2,4 @@ generate new age keys with `age-keygen -o ~/.config/sops/age/key-name.txt`. encrypt local secrets with `sops -e service-name/.env > service-name/.sops.env`. -the action installs the pinned, checksum-verified SOPS build for the runner's OS/arch and decrypts every `*.sops.*` file except `.sops.yaml`, writing `service-name/.sops.env` back to `service-name/.env` via a temp file and atomic move. +the action installs the pinned, checksum-verified SOPS build for the runner's OS/arch (skipping the download when `sops` is already on `PATH`, e.g. on the custom `studio/actions:ubuntu-latest` runner image) and decrypts every `*.sops.*` file except `.sops.yaml`, writing `service-name/.sops.env` back to `service-name/.env` via a temp file and atomic move. diff --git a/sops/action.yml b/sops/action.yml index 0697166..51c31e9 100644 --- a/sops/action.yml +++ b/sops/action.yml @@ -1,5 +1,5 @@ name: decrypt SOPS secrets -description: installs SOPS and decrypts all *.sops.* files using an age key +description: installs SOPS if missing and decrypts all *.sops.* files using an age key inputs: sops-age-key: @@ -17,6 +17,8 @@ runs: run: | set -euo pipefail + command -v sops >/dev/null && exit 0 + os=$(uname -s | tr '[:upper:]' '[:lower:]') arch=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/') asset="sops-${SOPS_VERSION}.${os}.${arch}" @@ -38,7 +40,6 @@ runs: SOPS_AGE_KEY: ${{ inputs.sops-age-key }} run: | set -euo pipefail - echo "searching for SOPS files to decrypt..." while IFS= read -r -d '' file; do @@ -46,9 +47,7 @@ runs: output_file="$dir/${base/.sops/}" echo "decrypting '$file' to '$output_file'" - tmp=$(mktemp "$dir/.sops-decrypt.XXXXXX") - if ! sops --decrypt "$file" > "$tmp" || [ ! -s "$tmp" ]; then echo "decryption of '$file' failed or produced empty output" >&2 rm -f "$tmp" @@ -58,5 +57,4 @@ runs: chmod 600 "$tmp" mv "$tmp" "$output_file" done < <(find . -type f -name "*.sops.*" -not -name ".sops.yaml" -print0) - echo "SOPS decryption complete." diff --git a/ssh-copy/action.yml b/ssh-copy/action.yml index 8a6bb34..f774141 100644 --- a/ssh-copy/action.yml +++ b/ssh-copy/action.yml @@ -29,6 +29,7 @@ runs: run: | set -euo pipefail command -v rsync >/dev/null && exit 0 + sudo apt-get -qq update sudo apt-get -yqq install rsync @@ -41,8 +42,10 @@ runs: run: | set -euo pipefail mkdir -p ~/.ssh + printf '%s\n' "$SSH_KEY" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 + ssh-keyscan -p "$PORT" -H "$HOST" >> ~/.ssh/known_hosts chmod 600 ~/.ssh/known_hosts diff --git a/ssh-run/action.yml b/ssh-run/action.yml index 3be1c1c..5606760 100644 --- a/ssh-run/action.yml +++ b/ssh-run/action.yml @@ -30,8 +30,10 @@ runs: run: | set -euo pipefail mkdir -p ~/.ssh + printf '%s\n' "$SSH_KEY" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 + ssh-keyscan -p "$PORT" -H "$HOST" >> ~/.ssh/known_hosts chmod 600 ~/.ssh/known_hosts