diff --git a/.github/workflows/pull-requests.yaml b/.github/workflows/pull-requests.yaml index 989e9f49..86055833 100644 --- a/.github/workflows/pull-requests.yaml +++ b/.github/workflows/pull-requests.yaml @@ -44,6 +44,17 @@ jobs: - name: Build Talos image run: make -C packages/core/installer talos-nocloud + + - name: Save git diff as patch + if: "!contains(github.event.pull_request.labels.*.name, 'release')" + run: git diff HEAD > _out/assets/pr.patch + + - name: Upload git diff patch + if: "!contains(github.event.pull_request.labels.*.name, 'release')" + uses: actions/upload-artifact@v4 + with: + name: pr-patch + path: _out/assets/pr.patch - name: Upload installer uses: actions/upload-artifact@v4 @@ -126,6 +137,10 @@ jobs: if: ${{ always() && (needs.build.result == 'success' || needs.resolve_assets.result == 'success') }} steps: + # ▸ Checkout and prepare the codebase + - name: Checkout code + uses: actions/checkout@v4 + # ▸ Regular PR path – download artefacts produced by the *build* job - name: "Download Talos image (regular PR)" if: "!contains(github.event.pull_request.labels.*.name, 'release')" @@ -134,6 +149,17 @@ jobs: name: talos-image path: _out/assets + - name: Download PR patch + if: "!contains(github.event.pull_request.labels.*.name, 'release')" + uses: actions/download-artifact@v4 + with: + name: pr-patch + path: _out/assets + + - name: Apply patch + if: "!contains(github.event.pull_request.labels.*.name, 'release')" + run: | + git apply _out/assets/pr.patch # ▸ Release PR path – fetch artefacts from the corresponding draft release - name: Download assets from draft release (release PR) @@ -145,23 +171,15 @@ jobs: env: GH_PAT: ${{ secrets.GH_PAT }} - # ▸ Start actual job steps - name: Set sandbox ID run: echo "SANDBOX_NAME=cozy-e2e-sandbox-$(echo "${GITHUB_REPOSITORY}:${GITHUB_WORKFLOW}:${GITHUB_REF}" | sha256sum | cut -c1-10)" >> $GITHUB_ENV + # ▸ Start actual job steps - name: Prepare workspace run: | - cd .. rm -rf /tmp/$SANDBOX_NAME - cp -r cozystack /tmp/$SANDBOX_NAME - sudo systemctl stop "rm-workspace-$SANDBOX_NAME.timer" "rm-workspace-$SANDBOX_NAME.service" 2>/dev/null || true - sudo systemctl reset-failed "rm-workspace-$SANDBOX_NAME.timer" "rm-workspace-$SANDBOX_NAME.service" 2>/dev/null || true - sudo systemctl daemon-reexec - sudo systemd-run \ - --on-calendar="$(date -d 'now + 24 hours' '+%Y-%m-%d %H:%M:%S')" \ - --unit=rm-workspace-$SANDBOX_NAME \ - rm -rf /tmp/$SANDBOX_NAME - + cp -r ${{ github.workspace }} /tmp/$SANDBOX_NAME + - name: Prepare environment run: | cd /tmp/$SANDBOX_NAME @@ -202,6 +220,11 @@ jobs: - name: Set sandbox ID run: echo "SANDBOX_NAME=cozy-e2e-sandbox-$(echo "${GITHUB_REPOSITORY}:${GITHUB_WORKFLOW}:${GITHUB_REF}" | sha256sum | cut -c1-10)" >> $GITHUB_ENV + - name: Sync _out/assets directory + run: | + mkdir -p /tmp/$SANDBOX_NAME/_out/assets + mv _out/assets/* /tmp/$SANDBOX_NAME/_out/assets/ + - name: Install Cozystack into sandbox run: | cd /tmp/$SANDBOX_NAME @@ -259,11 +282,3 @@ jobs: - name: Remove workspace run: rm -rf /tmp/$SANDBOX_NAME - - - name: Tear down timers - run: | - sudo systemctl stop "rm-workspace-$SANDBOX_NAME.timer" "rm-workspace-$SANDBOX_NAME.service" 2>/dev/null || true - sudo systemctl reset-failed "rm-workspace-$SANDBOX_NAME.timer" "rm-workspace-$SANDBOX_NAME.service" 2>/dev/null || true - sudo systemctl stop "teardown-$SANDBOX_NAME.timer" "teardown-$SANDBOX_NAME.service" 2>/dev/null || true - sudo systemctl reset-failed "teardown-$SANDBOX_NAME.timer" "teardown-$SANDBOX_NAME.service" 2>/dev/null || true - sudo systemctl daemon-reexec diff --git a/hack/e2e-install-cozystack.bats b/hack/e2e-install-cozystack.bats index a9abd59f..9138e466 100644 --- a/hack/e2e-install-cozystack.bats +++ b/hack/e2e-install-cozystack.bats @@ -1,5 +1,12 @@ #!/usr/bin/env bats +@test "Required installer assets exist" { + if [ ! -f _out/assets/cozystack-installer.yaml ]; then + echo "Missing: _out/assets/cozystack-installer.yaml" >&2 + exit 1 + fi +} + @test "Install Cozystack" { # Create namespace & configmap required by installer kubectl create namespace cozy-system --dry-run=client -o yaml | kubectl apply -f - diff --git a/hack/e2e-prepare-cluster.bats b/hack/e2e-prepare-cluster.bats index 5eb48f18..512a621b 100644 --- a/hack/e2e-prepare-cluster.bats +++ b/hack/e2e-prepare-cluster.bats @@ -4,11 +4,6 @@ # ----------------------------------------------------------------------------- @test "Required installer assets exist" { - if [ ! -f _out/assets/cozystack-installer.yaml ]; then - echo "Missing: _out/assets/cozystack-installer.yaml" >&2 - exit 1 - fi - if [ ! -f _out/assets/nocloud-amd64.raw.xz ]; then echo "Missing: _out/assets/nocloud-amd64.raw.xz" >&2 exit 1 diff --git a/packages/core/testing/Makefile b/packages/core/testing/Makefile index b7145cf3..a103cff6 100755 --- a/packages/core/testing/Makefile +++ b/packages/core/testing/Makefile @@ -15,7 +15,7 @@ help: ## Show this help. image: image-e2e-sandbox image-e2e-sandbox: - docker buildx build -f images/e2e-sandbox/Dockerfile ../../.. \ + docker buildx build -f images/e2e-sandbox/Dockerfile images/e2e-sandbox \ --provenance false \ --builder=$(BUILDER) \ --platform=$(PLATFORM) \ @@ -62,5 +62,5 @@ apply: delete -e TALOSCONFIG=/workspace/talosconfig \ -e KUBECONFIG=/workspace/kubeconfig \ "$$(yq .e2e.image values.yaml)" \ - sleep infinity + --timeout 30m docker cp "${ROOT_DIR}" "${SANDBOX_NAME}":/workspace diff --git a/packages/core/testing/images/e2e-sandbox/Dockerfile b/packages/core/testing/images/e2e-sandbox/Dockerfile index a51c841b..fdb2ee54 100755 --- a/packages/core/testing/images/e2e-sandbox/Dockerfile +++ b/packages/core/testing/images/e2e-sandbox/Dockerfile @@ -19,3 +19,6 @@ RUN curl -sSL "https://github.com/mikefarah/yq/releases/download/v4.44.3/yq_${TA && chmod +x /usr/local/bin/yq RUN curl -sSL "https://fluxcd.io/install.sh" | bash RUN curl -sSL "https://github.com/cozystack/cozypkg/raw/refs/heads/main/hack/install.sh" | sh -s -- -v "${COZYPKG_VERSION}" + +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/packages/core/testing/images/e2e-sandbox/entrypoint.sh b/packages/core/testing/images/e2e-sandbox/entrypoint.sh new file mode 100755 index 00000000..1e4a8b98 --- /dev/null +++ b/packages/core/testing/images/e2e-sandbox/entrypoint.sh @@ -0,0 +1,80 @@ +#!/bin/sh +set -eu + +SELF_PID="$$" +INTERVAL=30m + +while [ $# -gt 0 ]; do + case "$1" in + --timeout) + INTERVAL="$2" + shift 2 + ;; + *) + echo "Usage: $0 [--timeout SECONDS]" + exit 1 + ;; + esac +done + +ALL_PROCS=$(ps -eo pid=,ppid=,comm=) + +get_descendants() { + PARENT="$1" + echo "$PARENT" + echo "$ALL_PROCS" | while read -r PID PPID CMD; do + PID=$(echo "$PID" | tr -d ' ') + PPID=$(echo "$PPID" | tr -d ' ') + if [ "$PPID" = "$PARENT" ]; then + echo "$PID" + get_descendants "$PID" + fi + done +} + +is_own_tree() { + PID="$1" + echo "$DESCENDANTS" | grep -q -x "$PID" +} + +check_once() { + DESCENDANTS="$(get_descendants "$SELF_PID" | sort -u)" + EXTERNAL_PIDS=$( + echo "$ALL_PROCS" | while read -r PID PPID CMD; do + PID=$(echo "$PID" | tr -d ' ') + CMD=$(echo "$CMD" | tr -d ' ') + + if is_own_tree "$PID"; then + continue + fi + + case "$CMD" in + *qemu*) continue ;; + esac + + echo "PID=$PID CMD=$CMD" + done + ) + + COUNT=$(echo "$EXTERNAL_PIDS" | wc -w) + echo "$EXTERNAL_PIDS" + [ "$COUNT" -eq 0 ] +} + +check_loop() { + while :; do + ALL_PROCS=$(ps -eo pid=,ppid=,comm=) + + if check_once; then + echo "No external processes, exiting..." + exit 0 + fi + + echo "External processes still running, next check in ${INTERVAL}..." + sleep "$INTERVAL" + done +} + +echo "Waiting for external processes to be started, next check in ${INTERVAL}..." +sleep "$INTERVAL" +check_loop diff --git a/packages/core/testing/values.yaml b/packages/core/testing/values.yaml index 47321a36..bd00787e 100755 --- a/packages/core/testing/values.yaml +++ b/packages/core/testing/values.yaml @@ -1,2 +1,2 @@ e2e: - image: ghcr.io/cozystack/cozystack/e2e-sandbox:v0.32.1@sha256:b15f85e58be54529d74ab7056d5d47960944abde28f14611e88156989a19c789 + image: ghcr.io/cozystack/cozystack/e2e-sandbox:latest@sha256:df79b508c45ab11f728dfb12b5b984c04f64ea5c26cf239095913aa7fc9f73aa