Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions .github/actions/setup-go-ci/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Jobs with the same Go version and dependencies share setup-go's default cache.
# If a migration job saves it first, the archive lacks builds needed by tests.
# Later test jobs cannot update that saved archive, so they rebuild each run.
# Share downloaded modules, but give each workload a build cache that can refresh
# after source changes. Keep this policy here rather than repeating it in jobs.
name: Set up Go for CI
description: Install Go with shared module downloads and workload-specific build caches

# Composite action inputs are strings, unlike typed workflow_call inputs. Pass
# "true" or "false" for the boolean-like flags below; quote literals in callers.
inputs:
build-cache-scope:
description: >-
Free-form workload identifier, such as "postgres-18-race" or "sqlite-standard";
defaults to the workflow name and job ID. Test scopes must include backend/version
and race mode because Go also caches test results.
required: false
check-latest:
description: >-
String flag ("true" or "false"): "true" checks for the latest matching Go
version; "false" prefers an already installed matching version.
default: "false"
required: false
go-version:
description: Go version or selector, such as "1.27" or "stable"; takes precedence over go-version-file
required: false
go-version-file:
description: Repository-relative go.mod or go.work file to read when go-version is omitted
required: false
save-module-cache:
description: >-
String flag ("true" or "false"): "true" also saves downloads after a successful
job; "false" only restores them. Enable for a full-suite job, or the only Go
workload on a platform, so a smaller job cannot freeze a partial archive.
default: "false"
required: false

runs:
using: composite
steps:
- name: Install Go
id: go
uses: actions/setup-go@v7
with:
# This action manages module and build caches separately below.
cache: false
check-latest: ${{ inputs.check-latest }}
go-version: ${{ inputs.go-version }}
go-version-file: ${{ inputs.go-version-file }}

# Keep key components in step outputs so they do not leak into later steps.
# actions/cache remembers the primary key in its own private post-job state,
# but reads its path input again when saving. Only paths use GITHUB_ENV: nested
# composite outputs are unavailable when post inputs are resolved. These two
# names are job-wide, so prefix them and invoke this action once per job.
- name: Prepare cache paths and keys
id: cache-config
shell: bash
env:
BUILD_CACHE_SCOPE: ${{ inputs.build-cache-scope || format('{0}-{1}', github.workflow, github.job) }}
DEPENDENCY_HASH: ${{ hashFiles('**/go.mod', '**/go.sum', 'go.work', 'go.work.sum') }}
GO_VERSION: ${{ steps.go.outputs.go-version }}
SOURCE_HASH: ${{ hashFiles('**/*.go', '**/*.sql', '**/testdata/**', 'Makefile', '.github/actions/setup-go-ci/**', '.github/workflows/*.yaml') }}
run: |
module_cache_prefix="go-mod-v1-${RUNNER_OS}-${RUNNER_ARCH}"
build_cache_prefix="go-build-v1-${RUNNER_OS}-${RUNNER_ARCH}-${ImageOS:-$RUNNER_OS}-${GO_VERSION}-${BUILD_CACHE_SCOPE}"

{
echo "RIVER_GO_BUILD_CACHE=$(go env GOCACHE)"
echo "RIVER_GO_MOD_CACHE=$(go env GOMODCACHE)"
} >> "$GITHUB_ENV"

{
echo "build-prefix=$build_cache_prefix"
echo "dependency-hash=$DEPENDENCY_HASH"
echo "module-prefix=$module_cache_prefix"
echo "source-hash=$SOURCE_HASH"
} >> "$GITHUB_OUTPUT"

# Module caches contain downloads, not compiled code, so Go versions and race
# modes can share them. Hash every module's go.mod AND go.sum: version selection
# can change while go.sum still contains all the old checksums. Include workspace
# metadata too: go.work can select different local modules or replacements.
# The v1 prefix is our cache-layout version, independent of the action version.
#
# Full-suite jobs save this immutable archive; Windows has only the CLI job,
# so it saves its own downloads. A small Linux CLI/migration job would freeze
# an incomplete graph. Separate save/restore steps
# are deliberate: actions/cache saves in a post step; cache/restore never saves.
- name: Restore and save module cache
if: inputs.save-module-cache == 'true'
uses: actions/cache@v5
with:
path: ${{ env.RIVER_GO_MOD_CACHE }}
key: ${{ steps.cache-config.outputs.module-prefix }}-${{ steps.cache-config.outputs.dependency-hash }}
# Reuse older downloads after dependency changes; Go still selects the
# requested versions and verifies checksums, fetching anything missing.
restore-keys: |
${{ steps.cache-config.outputs.module-prefix }}-

- name: Restore module cache
if: inputs.save-module-cache != 'true'
uses: actions/cache/restore@v5
with:
path: ${{ env.RIVER_GO_MOD_CACHE }}
key: ${{ steps.cache-config.outputs.module-prefix }}-${{ steps.cache-config.outputs.dependency-hash }}
restore-keys: |
${{ steps.cache-config.outputs.module-prefix }}-

# Builds are scoped by OS, architecture, runner image, exact Go version, and
# workload. Separate race/non-race scopes keep both warm; Go itself can safely
# distinguish their artifacts. Database-version scopes also isolate cached
# test results because Go cannot detect changes to an external database.
- name: Restore and save build cache
uses: actions/cache@v5
with:
path: ${{ env.RIVER_GO_BUILD_CACHE }}
# Archives cannot be updated in place. A new Go/CI input hash lets the job
# save its fresh artifacts. SQL/testdata hashes cover embedded migrations and
# fixtures too; unrelated port implementation/docs edits keep the same key.
key: ${{ steps.cache-config.outputs.build-prefix }}-${{ steps.cache-config.outputs.dependency-hash }}-${{ steps.cache-config.outputs.source-hash }}
# Search from most to least specific: first drop the source hash, then
# the dependency hash. Both fallbacks retain toolchain/workload scope;
# Go validates its own inputs and rebuilds anything that no longer matches.
restore-keys: |
${{ steps.cache-config.outputs.build-prefix }}-${{ steps.cache-config.outputs.dependency-hash }}-
${{ steps.cache-config.outputs.build-prefix }}-
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ updates:
patterns:
- "*"
- package-ecosystem: "github-actions"
# The JavaScript workflows' composite actions live under .github/actions.
# Scan every local composite action as well as the workflows.
directories:
- "/"
- "/.github/actions/*"
Expand Down
58 changes: 36 additions & 22 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ jobs:
steps:
- uses: actions/checkout@v7

- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v7
- name: Set up Go ${{ matrix.go-version }} for CI
uses: ./.github/actions/setup-go-ci
with:
build-cache-scope: benchmark-postgres-${{ matrix.postgres-version }}
go-version: ${{ matrix.go-version }}

- name: Display Go version
Expand Down Expand Up @@ -123,9 +124,15 @@ jobs:
steps:
- uses: actions/checkout@v7

- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v7
- name: Set up Go ${{ matrix.go-version }} for CI
uses: ./.github/actions/setup-go-ci
with:
# Go's test-result cache cannot detect a different Postgres server.
# Keep each database version and race mode in its own build archive.
build-cache-scope: postgres-${{ matrix.postgres-version }}-${{ matrix.primary && 'race' || 'standard' }}
# Only the full primary suite may publish the shared module archive;
# verification/CLI jobs download only a subset of the dependencies.
save-module-cache: "${{ matrix.primary == true }}"
go-version: ${{ matrix.go-version }}

- name: Display Go version
Expand Down Expand Up @@ -162,9 +169,10 @@ jobs:
steps:
- uses: actions/checkout@v7

- name: Setup Go ${{ matrix.go-version }}
uses: actions/setup-go@v7
- name: Set up Go ${{ matrix.go-version }} for CI
uses: ./.github/actions/setup-go-ci
with:
build-cache-scope: sqlite-${{ matrix.primary && 'race' || 'standard' }}
go-version: ${{ matrix.go-version }}

- name: Test with race detector
Expand All @@ -184,6 +192,10 @@ jobs:
timeout-minutes: 10

steps:
# Load the local action and dependency files before restoring caches.
- name: Checkout
uses: actions/checkout@v7

# CLI tests use each runner's bundled Postgres version; the database
# test matrix above covers supported Postgres versions separately.
# GitHub's Linux image includes Postgres with its service disabled.
Expand Down Expand Up @@ -228,10 +240,13 @@ jobs:
# adds the bundled client tools to PATH for all subsequent steps.
$env:PGBIN | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- uses: actions/setup-go@v7
- uses: ./.github/actions/setup-go-ci
with:
# Windows has no full-suite job, so its only Go workload must save
# its own module downloads. Linux uses the primary suite's archive.
save-module-cache: "${{ runner.os == 'Windows' }}"
go-version: "stable"
check-latest: true
check-latest: "true"

- name: Setup GOBIN (Linux)
if: runner.os == 'Linux'
Expand All @@ -248,9 +263,6 @@ jobs:
echo $gobin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
shell: pwsh

- name: Checkout
uses: actions/checkout@v7

- name: export RIVER_CMD_DIR
run: |
if [ "$RUNNER_OS" == "Linux" ]; then
Expand Down Expand Up @@ -377,14 +389,15 @@ jobs:
pull-requests: read

steps:
- uses: actions/setup-go@v7
with:
go-version: "stable"
check-latest: true

# Load the local action and dependency files before restoring caches.
- name: Checkout
uses: actions/checkout@v7

- uses: ./.github/actions/setup-go-ci
with:
go-version: "stable"
check-latest: "true"

- name: Lint
uses: golangci/golangci-lint-action@v9
with:
Expand All @@ -409,7 +422,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v7

- uses: actions/setup-go@v7
- uses: ./.github/actions/setup-go-ci
with:
go-version: "1.27"

Expand All @@ -435,14 +448,15 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/setup-go@v7
with:
go-version: "stable"
check-latest: true

# Load the local action and dependency files before restoring caches.
- name: Checkout
uses: actions/checkout@v7

- uses: ./.github/actions/setup-go-ci
with:
go-version: "stable"
check-latest: "true"

- name: Check all go/toolchain directives match
run: CHECK=true make update-mod-go

Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/conformance.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
branches:
- master
paths:
- ".github/actions/setup-go-ci/**"
- ".github/workflows/conformance.yaml"
- "Makefile"
- "**.go"
Expand All @@ -20,6 +21,7 @@ on:
- "riverdriver/**/*.sql"
pull_request:
paths:
- ".github/actions/setup-go-ci/**"
- ".github/workflows/conformance.yaml"
- "Makefile"
- "**.go"
Expand Down Expand Up @@ -51,7 +53,7 @@ jobs:
with:
persist-credentials: false

- uses: actions/setup-go@v7
- uses: ./.github/actions/setup-go-ci
with:
go-version-file: go.work

Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/java.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
branches:
- master
paths:
- ".github/actions/setup-go-ci/**"
- ".github/actions/setup-java/**"
- ".github/workflows/java.yaml"
- "Makefile"
Expand All @@ -15,6 +16,7 @@ on:
- "riverdriver/riversqlite/migration/**"
pull_request:
paths:
- ".github/actions/setup-go-ci/**"
- ".github/actions/setup-java/**"
- ".github/workflows/java.yaml"
- "Makefile"
Expand Down Expand Up @@ -44,7 +46,7 @@ jobs:

- uses: ./.github/actions/setup-java

- uses: actions/setup-go@v7
- uses: ./.github/actions/setup-go-ci
with:
go-version-file: go.work

Expand Down Expand Up @@ -85,7 +87,7 @@ jobs:
with:
java-version: ${{ matrix.java-version }}

- uses: actions/setup-go@v7
- uses: ./.github/actions/setup-go-ci
with:
go-version-file: go.work

Expand Down Expand Up @@ -124,7 +126,7 @@ jobs:

- uses: ./.github/actions/setup-java

- uses: actions/setup-go@v7
- uses: ./.github/actions/setup-go-ci
with:
go-version-file: go.work

Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/js.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
branches:
- master
paths:
- ".github/actions/setup-go-ci/**"
- ".github/actions/setup-js/**"
- ".github/workflows/js.yaml"
- "Makefile"
Expand All @@ -16,6 +17,7 @@ on:
tags: ["js/v*"]
pull_request:
paths:
- ".github/actions/setup-go-ci/**"
- ".github/actions/setup-js/**"
- ".github/workflows/js.yaml"
- "Makefile"
Expand Down Expand Up @@ -192,7 +194,7 @@ jobs:

# Some unit tests read fixtures generated from River's Go
# implementation.
- uses: actions/setup-go@v7
- uses: ./.github/actions/setup-go-ci
with:
go-version-file: go.work

Expand Down Expand Up @@ -246,7 +248,7 @@ jobs:
node-version: ${{ matrix.node-version }}

# The resumable integration scenarios read Go-generated fixtures.
- uses: actions/setup-go@v7
- uses: ./.github/actions/setup-go-ci
with:
go-version-file: go.work

Expand Down
Loading
Loading