diff --git a/actions/golang/cache-s3/action.yaml b/actions/golang/cache-s3/action.yaml new file mode 100644 index 00000000..d90172c6 --- /dev/null +++ b/actions/golang/cache-s3/action.yaml @@ -0,0 +1,81 @@ +name: Setup S3-backed cache for a Golang application (Hetzner RGW) +author: 'MiLaboratories' +description: | + S3-backed sibling of golang/cache. Restores/saves the Go module + build + caches to an S3 endpoint (the Hetzner RadosGW at s3.hz.platforma.bio) via + tespkg/actions-cache, instead of the GitHub-hosted cache. + + Use on the hz self-hosted runners (hz-rl8-*, hz-ubuntu-dind): the cache is + restored per-job and saved on success, so there is no shared-hostPath cache + on the node and therefore no cross-job contamination. Linux only (the hz + fleet is Linux/x86); macOS/Windows jobs keep using golang/cache. + + The cache key scheme is identical to golang/cache, so switching backends + does not change keys. + +inputs: + cache-version: + description: | + Change this value to 'reset' the cache for a job (forces a cold build). + required: false + default: 'v1' + cache-dependency-hashfiles-path: + description: | + hashFiles() pattern that produces the cache key suffix. + required: false + default: '**/go.work.sum' + + # --- S3 / RadosGW --- + endpoint: + description: "S3 endpoint host, no scheme (split-DNS: resolves to the in-cluster RGW on hz, public elsewhere)." + required: false + default: 's3.hz.platforma.bio' + bucket: + description: "S3 bucket." + required: false + default: 'ci-actions-cache' + region: + description: "S3 region." + required: false + default: 'us-east-1' + insecure: + description: "Use plain HTTP instead of TLS to the endpoint." + required: false + default: 'false' + access-key: + description: "S3 access key (pass from the org secret HZ_CI_CACHE_S3_ACCESS_KEY)." + required: true + secret-key: + description: "S3 secret key (pass from the org secret HZ_CI_CACHE_S3_SECRET_KEY)." + required: true + use-fallback: + description: "Fall back to the GitHub-hosted cache if the S3 endpoint is unreachable." + required: false + default: 'true' + +runs: + using: "composite" + steps: + - name: Cache Golang modules in S3 (RGW) + uses: tespkg/actions-cache@e07e2d4953dc8c020d447363e5064e36d04f3cf9 # v1.10.2 + with: + endpoint: ${{ inputs.endpoint }} + region: ${{ inputs.region }} + bucket: ${{ inputs.bucket }} + insecure: ${{ inputs.insecure }} + accessKey: ${{ inputs.access-key }} + secretKey: ${{ inputs.secret-key }} + use-fallback: ${{ inputs.use-fallback }} + retry: 'true' + retry-count: '3' + # Only the build cache — NOT ~/go/pkg/mod. The module cache is read-only + # (0444) and tespkg/actions-cache extracts with `tar --keep-old-files`, + # which fails ("Cannot open: File exists") on the module cache; the build + # cache is the real compile-time win, and modules repopulate from + # GOPROXY (use a cached-only proxy). (Stock actions/cache overwrote, so + # this only bites the S3-backed action.) + path: | + ~/.cache/go-build + key: ${{ runner.os }}-${{ runner.arch }}-cache-go-${{ inputs.cache-version }}-${{ hashFiles(inputs.cache-dependency-hashfiles-path) }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-cache-go-${{ inputs.cache-version }}- diff --git a/actions/golang/prepare/action.yaml b/actions/golang/prepare/action.yaml index 3e4bab86..2e174997 100644 --- a/actions/golang/prepare/action.yaml +++ b/actions/golang/prepare/action.yaml @@ -48,6 +48,15 @@ inputs: required: false default: 'true' + cache-enabled: + description: | + Run the built-in golang/cache step (GitHub actions/cache). Set to 'false' + to skip it — e.g. when the caller provides its own cache (the s3/RGW + golang/cache-s3 sibling on self-hosted runners), to avoid two caches + fighting over the same paths. + required: false + default: 'true' + runs: using: "composite" @@ -60,6 +69,7 @@ runs: cache: ${{ inputs.cache-enabled-in-setup-go }} - name: Setup Cache for Golang project + if: inputs.cache-enabled == 'true' uses: milaboratory/github-ci/actions/golang/cache@v4 with: cache-version: ${{ inputs.cache-version }} diff --git a/actions/node/cache-pnpm-s3/action.yaml b/actions/node/cache-pnpm-s3/action.yaml new file mode 100644 index 00000000..700e6c43 --- /dev/null +++ b/actions/node/cache-pnpm-s3/action.yaml @@ -0,0 +1,76 @@ +name: Cache NodeJS PNPM in S3 (Hetzner RGW) +author: 'MiLaboratories' +description: | + S3-backed sibling of node/cache-pnpm. Restores/saves the pnpm content- + addressable store to the Hetzner RadosGW (s3.hz.platforma.bio) via + tespkg/actions-cache, instead of the GitHub-hosted cache. Use on the hz + self-hosted runners. Linux only. + + The pnpm store path is resolved dynamically (`pnpm store path`), so it works + regardless of where the runner image places the store. The cache key scheme + is identical to node/cache-pnpm. + +inputs: + cache-version: + description: "Change this value to 'reset' the cache for a job." + required: false + default: 'v1' + cache-hashfiles-search-path: + description: "hashFiles() pattern for pnpm-lock.yaml." + required: false + default: '**/pnpm-lock.yaml' + + # --- S3 / RadosGW --- + endpoint: + description: "S3 endpoint host, no scheme." + required: false + default: 's3.hz.platforma.bio' + bucket: + description: "S3 bucket." + required: false + default: 'ci-actions-cache' + region: + description: "S3 region." + required: false + default: 'us-east-1' + insecure: + description: "Use plain HTTP instead of TLS to the endpoint." + required: false + default: 'false' + access-key: + description: "S3 access key (pass from the org secret HZ_CI_CACHE_S3_ACCESS_KEY)." + required: true + secret-key: + description: "S3 secret key (pass from the org secret HZ_CI_CACHE_S3_SECRET_KEY)." + required: true + use-fallback: + description: "Fall back to the GitHub-hosted cache if the S3 endpoint is unreachable." + required: false + default: 'true' + +runs: + using: "composite" + steps: + - name: Get pnpm store path + id: pnpm-store-dir + shell: bash + run: echo "dir=$(pnpm store path)" >> ${GITHUB_OUTPUT} + + - name: Cache Node modules in S3 (RGW) + uses: tespkg/actions-cache@e07e2d4953dc8c020d447363e5064e36d04f3cf9 # v1.10.2 + with: + endpoint: ${{ inputs.endpoint }} + region: ${{ inputs.region }} + bucket: ${{ inputs.bucket }} + insecure: ${{ inputs.insecure }} + accessKey: ${{ inputs.access-key }} + secretKey: ${{ inputs.secret-key }} + use-fallback: ${{ inputs.use-fallback }} + retry: 'true' + retry-count: '3' + path: | + ${{ steps.pnpm-store-dir.outputs.dir }} + ~/.pnpm-store + key: ${{ runner.os }}-${{ runner.arch }}-cache-pnpm-${{ inputs.cache-version }}-genericnodejs-${{ hashFiles(inputs.cache-hashfiles-search-path) }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-cache-pnpm-${{ inputs.cache-version }}-genericnodejs- diff --git a/actions/rust/cache-s3/action.yaml b/actions/rust/cache-s3/action.yaml new file mode 100644 index 00000000..0a0bad55 --- /dev/null +++ b/actions/rust/cache-s3/action.yaml @@ -0,0 +1,80 @@ +name: Setup S3-backed cache for a Rust application (Hetzner RGW) +author: 'MiLaboratories' +description: | + S3-backed sibling of rust/cache. Restores/saves the Cargo registry/git caches + and the target/ dir to the Hetzner RadosGW (s3.hz.platforma.bio) via + tespkg/actions-cache, instead of the GitHub-hosted cache. Use on the hz + self-hosted runners. Linux only. + + NOTE: the hz-rl8 runner image bakes CARGO_HOME=/opt/rust/cargo (the rustup + install lives there), so the Cargo registry cache lands under that path, not + ~/.cargo. Pass cargo-home accordingly when consuming on rl8. + + The cache key scheme is identical to rust/cache. + +inputs: + cache-version: + description: "Change this value to 'reset' the cache for a job." + required: false + default: 'v1' + cache-hashfiles-search-path: + description: "hashFiles() pattern for Cargo.lock." + required: false + default: '**/Cargo.lock' + cargo-home: + description: "CARGO_HOME path (hz-rl8 image bakes /opt/rust/cargo; default assumes ~/.cargo)." + required: false + default: '~/.cargo' + + # --- S3 / RadosGW --- + endpoint: + description: "S3 endpoint host, no scheme." + required: false + default: 's3.hz.platforma.bio' + bucket: + description: "S3 bucket." + required: false + default: 'ci-actions-cache' + region: + description: "S3 region." + required: false + default: 'us-east-1' + insecure: + description: "Use plain HTTP instead of TLS to the endpoint." + required: false + default: 'false' + access-key: + description: "S3 access key (pass from the org secret HZ_CI_CACHE_S3_ACCESS_KEY)." + required: true + secret-key: + description: "S3 secret key (pass from the org secret HZ_CI_CACHE_S3_SECRET_KEY)." + required: true + use-fallback: + description: "Fall back to the GitHub-hosted cache if the S3 endpoint is unreachable." + required: false + default: 'true' + +runs: + using: "composite" + steps: + - name: Cache Rust Cargo modules in S3 (RGW) + uses: tespkg/actions-cache@e07e2d4953dc8c020d447363e5064e36d04f3cf9 # v1.10.2 + with: + endpoint: ${{ inputs.endpoint }} + region: ${{ inputs.region }} + bucket: ${{ inputs.bucket }} + insecure: ${{ inputs.insecure }} + accessKey: ${{ inputs.access-key }} + secretKey: ${{ inputs.secret-key }} + use-fallback: ${{ inputs.use-fallback }} + retry: 'true' + retry-count: '3' + path: | + ${{ inputs.cargo-home }}/bin/ + ${{ inputs.cargo-home }}/registry/index/ + ${{ inputs.cargo-home }}/registry/cache/ + ${{ inputs.cargo-home }}/git/db/ + target/ + key: ${{ runner.os }}-${{ runner.arch }}-cache-rust-${{ inputs.cache-version }}-${{ hashFiles(inputs.cache-hashfiles-search-path) }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-cache-rust-${{ inputs.cache-version }}-