Skip to content
Open
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
21 changes: 6 additions & 15 deletions .github/actions/e2e-cluster-up/action.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: E2E cluster up
description: >-
Shared E2E setup: free disk, install k3d and Tilt from the e2e-tools artifact,
create the k3d cluster, and set up /etc/hosts. Used by the e2e-tests and e2e-ui
jobs so their setup can't drift. The caller must run actions/checkout and
actions/setup-go first (this action references the repo and `go env GOPATH`).
Shared E2E setup: free disk, create the k3d cluster, and set up /etc/hosts.
Used by the e2e-tests and e2e-ui jobs so their setup can't drift. The caller
must run actions/checkout and .github/actions/setup-nix first: this action
references the repo, and k3d and kubectl come from the development shell.

inputs:
k8s-version:
Expand All @@ -30,29 +30,20 @@ runs:
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /usr/local/.ghcup /opt/hostedtoolcache/CodeQL
printf "==> Available space after cleanup\n"
df -h
- name: Download k3d and Tilt
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: e2e-tools
path: tools-bin
- name: Install k3d and Tilt onto PATH
# built once by the e2e-tools job; artifacts don't preserve the +x bit
shell: bash
run: install -m 0755 tools-bin/k3d tools-bin/tilt "$(go env GOPATH)/bin/"
- name: Install socat
# socat supports "kubectl port-forward": cri-dockerd needed it (https://github.com/k3s-io/cri-dockerd/blob/4995f339edcffdf890406b3f1477d34e38477f18/streaming/streaming_others.go#L46);
# k3d's k3s uses embedded containerd, which doesn't, so this is defensive and harmless.
shell: bash
run: sudo apt-get -y install socat
- name: Create k3d cluster
shell: bash
shell: nix develop --command bash --noprofile --norc -eo pipefail {0}
env:
KUBECONFIG: ${{ inputs.kubeconfig }}
# hack/tilt/k3d-up.sh maps this key via hack/k8s-versions.sh to a k3s image
K8S_VERSION: ${{ inputs.k8s-version }}
CLI_AUTH_KUBECONFIG: ${{ inputs.cli-auth-kubeconfig }}
run: |
# k3d and Tilt come from the e2e-tools artifact (installed above).
# k3d and kubectl come from the development shell.
# k3d runs k3s with its embedded containerd (2.x in these k3s
# versions), which supports the Kubernetes image volumes the
# init-less pod layout uses to deliver argoexec.
Expand Down
13 changes: 8 additions & 5 deletions .github/actions/e2e-failure-debug/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,28 @@ description: >-
guarded with `|| true` so one failing diagnostic doesn't skip the rest — a
composite step otherwise aborts the whole action on the first failure.

Each step runs in the development shell, which is where `kubectl` comes from,
so the caller must have run .github/actions/setup-nix.

runs:
using: composite
steps:
- name: Failure debug - k3d server logs
shell: bash
shell: nix develop --command bash --noprofile --norc -eo pipefail {0}
run: docker logs k3d-k3s-default-server-0 || true
- name: Failure debug - Controller/API logs
shell: bash
shell: nix develop --command bash --noprofile --norc -eo pipefail {0}
run: |
kubectl -n argo logs deploy/workflow-controller --prefix --tail=-1 || true
kubectl -n argo logs deploy/argo-server --prefix --tail=-1 || true
- name: Failure debug - Tilt logs
shell: bash
shell: nix develop --command bash --noprofile --norc -eo pipefail {0}
run: '[ -e /tmp/tilt.log ] && cat /tmp/tilt.log || true'
- name: Failure debug - describe Workflows
shell: bash
shell: nix develop --command bash --noprofile --norc -eo pipefail {0}
run: |
kubectl get wf || true
kubectl describe wf || true
- name: Failure debug - Workflow Pod logs
shell: bash
shell: nix develop --command bash --noprofile --norc -eo pipefail {0}
run: kubectl logs --all-containers -l workflows.argoproj.io/workflow --prefix || true
19 changes: 19 additions & 0 deletions .github/actions/yarn-cache/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Cache the Yarn download cache
description: >-
Restore and save Yarn's global download cache. Jobs that get Node and Yarn
from the development shell rather than `actions/setup-node` lose the caching
that action did as a side effect; this puts it back, on its own, so that
fetching the same packages again is not the price of moving to Nix.

Only the download cache is shared: `yarn install` still links `ui/node_modules`
in each job, exactly as it did before.

runs:
using: composite
steps:
- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cache/yarn
key: ${{ runner.os }}-yarn-${{ hashFiles('ui/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
115 changes: 47 additions & 68 deletions .github/workflows/ci-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,11 @@ jobs:
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.26"
cache: true
- run: make test STATIC_FILES=false GOTEST='go test -p 20 -covermode=atomic -coverprofile=coverage.out'
# Go and gotestsum come from the development shell, so the tests run on
# the toolchain go.mod asks for and report through the pinned runner.
- uses: ./.github/actions/setup-nix
- uses: ./.github/actions/go-cache
- run: nix develop --command make test STATIC_FILES=false GOTEST='go test -p 20 -covermode=atomic -coverprofile=coverage.out'
- name: Upload test results
if: ${{ always() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
Expand All @@ -164,6 +164,8 @@ jobs:
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# The development shell is Linux and macOS only, so Windows keeps its own
# Go install; the version below has to be kept in step with go.mod by hand.
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.26"
Expand All @@ -181,40 +183,9 @@ jobs:
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

e2e-tools:
name: E2E Tools
needs: [ changed-files ]
# also required by e2e-ui (runs on ui-only changes); keep this condition a
# superset of e2e-ui's, else a skipped dependency cascades and e2e-ui is
# silently skipped on ui-only PRs
if: ${{ needs.changed-files.outputs.e2e-tests == 'true' || needs.changed-files.outputs.ui == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.26"
cache: true
- name: Build k3d and Tilt once
# The whole e2e matrix shares these binaries via the artifact below, so
# we hit the k3d module proxy and the Tilt release CDN once each — not in
# ~14 parallel jobs, which throttles the CDN. This is why neither install
# needs download retries.
run: |
make k3d tilt
mkdir -p tools-bin
cp "$(go env GOPATH)/bin/k3d" "$(go env GOPATH)/bin/tilt" tools-bin/
- name: Upload tools
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: e2e-tools
path: tools-bin
if-no-files-found: error

e2e-tests:
name: E2E Tests
needs: [ changed-files, e2e-tools ]
needs: [ changed-files ]
if: ${{ needs.changed-files.outputs.e2e-tests == 'true' }}
runs-on: ubuntu-24.04
# These tests usually finish in ~25m, but occasionally they take much longer due to resource
Expand All @@ -223,6 +194,13 @@ jobs:
env:
KUBECONFIG: /home/runner/.kube/config
E2E_ENV_FACTOR: 2
defaults:
run:
# Every step below wants something from the development shell — Tilt,
# k3d, kubectl, Go, gotestsum — so the job runs in it rather than
# prefixing each `run` with `nix develop --command`. Everything the
# runner image provides (Docker above all) is still on PATH behind it.
shell: nix develop --command bash --noprofile --norc -eo pipefail {0}
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -331,17 +309,23 @@ jobs:
use-api: false
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.26"
cache: true
- name: Install Java for the SDK
if: ${{matrix.test == 'test-java-sdk'}}
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0
# The JDK the Java SDK suite builds with comes from the shell too — it is
# pinned there alongside the OpenAPI Generator that produced the client.
# Maven itself still comes from the runner image, as it always did:
# `actions/setup-java` installed a JDK, not Maven.
- uses: ./.github/actions/setup-nix
- uses: ./.github/actions/go-cache
- name: Cache the Maven repository
# `actions/setup-java` cached this as a side effect; only the Java SDK
# leg builds anything with Maven, so restore it only there.
if: ${{ matrix.test == 'test-java-sdk' }}
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
java-version: '8'
distribution: adopt
cache: maven
path: ~/.m2/repository
# the client pom is generated, so key on what generates it
key: ${{ runner.os }}-maven-${{ hashFiles('sdks/java/tests/pom.xml', 'sdks/java/Makefile') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Set up k3d cluster and E2E tooling
uses: ./.github/actions/e2e-cluster-up
with:
Expand Down Expand Up @@ -421,18 +405,13 @@ jobs:
# see https://github.com/orgs/community/discussions/9141#discussioncomment-2296809 and https://github.com/orgs/community/discussions/26822#discussioncomment-3305794
e2e-tests-composite-result:
name: E2E Tests - Composite result
needs: [ e2e-tools, e2e-tests, e2e-ui ]
needs: [ e2e-tests, e2e-ui ]
if: ${{ always() }}
runs-on: ubuntu-24.04
steps:
- run: |
tools="${{ needs.e2e-tools.result }}"
result="${{ needs.e2e-tests.result }}"
ui="${{ needs.e2e-ui.result }}"
# a tools failure skips the dependent jobs, which must not count as a pass
if [[ $tools == "failure" ]]; then
exit 1
fi
# mark as successful even if skipped (e.g. a PR that touches neither)
if [[ ( $result == "success" || $result == "skipped" ) && ( $ui == "success" || $ui == "skipped" ) ]]; then
exit 0
Expand Down Expand Up @@ -496,13 +475,15 @@ jobs:
timeout-minutes: 6
env:
NODE_OPTIONS: --max-old-space-size=4096
defaults:
run:
# Node and Yarn come from the development shell, so the bundle CI builds
# is the one built locally; every step here needs them.
shell: nix develop --command bash --noprofile --norc -eo pipefail {0}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24" # change in all GH Workflows
cache: yarn
cache-dependency-path: ui/yarn.lock
- uses: ./.github/actions/setup-nix
- uses: ./.github/actions/yarn-cache
- run: yarn --cwd ui install
- run: yarn --cwd ui build
- run: yarn --cwd ui test
Expand All @@ -518,7 +499,7 @@ jobs:

e2e-ui:
name: E2E UI
needs: [ changed-files, e2e-tools ]
needs: [ changed-files ]
if: ${{ needs.changed-files.outputs.ui == 'true' || needs.changed-files.outputs.e2e-tests == 'true' }}
runs-on: ubuntu-24.04
timeout-minutes: 30
Expand All @@ -530,17 +511,15 @@ jobs:
# argo-server serves the production UI bundle at :2746. Point Playwright
# there — this also gives production-bundle coverage.
ARGO_UI_BASE_URL: http://localhost:2746
defaults:
run:
# As in e2e-tests: Tilt, k3d, kubectl, Node and Yarn all come from the
# development shell, so the whole job runs in it.
shell: nix develop --command bash --noprofile --norc -eo pipefail {0}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: "1.26"
cache: true
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24" # change in all GH Workflows
cache: yarn
cache-dependency-path: ui/yarn.lock
- uses: ./.github/actions/setup-nix
- uses: ./.github/actions/yarn-cache
- name: Set up k3d cluster and E2E tooling
uses: ./.github/actions/e2e-cluster-up
- name: Install UI dependencies and Playwright browser
Expand Down
13 changes: 6 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -593,8 +593,8 @@ dist/argosay:
cp test/e2e/images/argosay/v2/argosay dist/

# The development shell supplies tilt and k3d, so these two targets exist only
# for the environments that do not use it yet: CI and the dev container. They go
# when those move to the flake.
# for the dev container, which does not use it yet. They go when it moves to the
# flake.

# renovate: datasource=github-releases depName=tilt-dev/tilt
TILT_VERSION ?= 0.37.3
Expand All @@ -609,9 +609,8 @@ tilt: ## Install the pinned Tilt to $(GOPATH)/bin if not already present
dir=$$(go env GOPATH)/bin ; mkdir -p "$$dir" ; \
echo "installing tilt v$(TILT_VERSION) to $$dir" ; \
: "tilt can't be go installed (its go.mod has replace directives), so it" ; \
: "comes from GitHub's release CDN. CI builds it once (the e2e-tools job)" ; \
: "and shares it across the matrix, rather than fetching it in 14 parallel" ; \
: "jobs (which throttles the CDN) — so no download retries are needed." ; \
: "comes from GitHub's release CDN. One download per dev container build" ; \
: "doesn't need retries; CI gets tilt from the shell, not from here." ; \
: "Download to a temp file so a truncated download fails tar cleanly." ; \
tmp=$$(mktemp) ; \
curl -fsSL "https://github.com/tilt-dev/tilt/releases/download/v$(TILT_VERSION)/tilt.$(TILT_VERSION).$$os.$$arch.tar.gz" -o "$$tmp" \
Expand All @@ -625,8 +624,8 @@ k3d: ## Install the pinned k3d to $(GOPATH)/bin if not already present
else \
echo "installing k3d v$${K3D_VERSION}" ; \
: "go install pulls from the module proxy (proxy.golang.org), which is" ; \
: "far more reliable under CI load than GitHub's release-asset CDN. The" ; \
: "ldflags stamp the version k3d reports and uses to tag its helper image" ; \
: "more reliable than GitHub's release-asset CDN. The ldflags stamp the" ; \
: "version k3d reports and uses to tag its helper image" ; \
go install -ldflags "-X github.com/k3d-io/k3d/v5/version.Version=v$${K3D_VERSION}" \
github.com/k3d-io/k3d/v5@v$${K3D_VERSION} ; \
fi
Expand Down
4 changes: 3 additions & 1 deletion cmd/argoexec/commands/emissary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ func TestEmissary(t *testing.T) {
})
t.Run("Sub-process", func(t *testing.T) {
_ = os.Remove(varRunArgo + "/ctr/main/stdout")
err = run(`(sleep 60; echo 'should not wait for sub-process')& echo "hello\c"`)
// `printf`, not `echo "hello\c"`: only dash reads that as "hello with no
// newline", and `sh` is bash on macOS and inside the development shell.
err = run(`(sleep 60; echo 'should not wait for sub-process')& printf hello`)
require.NoError(t, err)
var data []byte
data, err = os.ReadFile(varRunArgo + "/ctr/main/stdout")
Expand Down
6 changes: 6 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,14 @@
# Nix's Go sets its own GOROOT; a stale one inherited from the host
# (a Homebrew or asdf install, say) makes it build against the wrong
# standard library.
#
# Nix also points TMPDIR at a directory of its own, whose name is 17
# characters longer than /tmp. Go tests that bind a unix socket under
# `t.TempDir()` then run past the 108-byte sun_path limit and fail
# only inside the shell, so hand TMPDIR back to the platform default.
shellHook = ''
unset GOROOT
unset TMPDIR TMP TEMP TEMPDIR
'';
};

Expand Down
7 changes: 6 additions & 1 deletion workflow/executor/osspecific/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ import (
func TestSimpleStartCloser(t *testing.T) {
ctx := logging.TestContext(t.Context())
shell := "sh"
// `echo "...\c"` drops the trailing newline under dash, but prints the
// backslash verbatim under bash — which is what `sh` is on macOS and inside
// the development shell. `printf` means the same thing under both.
command := `printf '%s' "A123456789B123456789C123456789D123456789E123456789"`
if runtime.GOOS == "windows" {
shell = "pwsh.exe"
command = `echo "A123456789B123456789C123456789D123456789E123456789\c"`
}
cmd := exec.CommandContext(ctx, shell, "-c", `echo "A123456789B123456789C123456789D123456789E123456789\c"`)
cmd := exec.CommandContext(ctx, shell, "-c", command)
var stdoutWriter bytes.Buffer
slowWriter := SlowWriter{
&stdoutWriter,
Expand Down
Loading