name: cloud-runner-integrity on: workflow_call: inputs: runGithubIntegrationTests: description: 'Run GitHub Checks integration tests' required: false default: 'false' type: string permissions: contents: read checks: write statuses: write env: # Commented out: Using LocalStack tests instead of real AWS # AWS_REGION: eu-west-2 # AWS_DEFAULT_REGION: eu-west-2 AWS_STACK_NAME: game-ci-team-pipelines # Still needed for LocalStack S3 bucket creation CLOUD_RUNNER_BRANCH: ${{ github.ref }} DEBUG: true PROJECT_PATH: test-project USE_IL2CPP: false jobs: k8s: name: Cloud Runner Tests (K8s) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: lfs: false # Set up Kubernetes (k3s via k3d) - name: Set up kubectl uses: azure/setup-kubectl@v4 with: version: 'v1.34.1' - name: Install k3d run: | curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash k3d version | cat - name: Start LocalStack (S3) uses: localstack/setup-localstack@v0.2.4 with: install-awslocal: true - name: Verify LocalStack is running run: | echo "Checking LocalStack status..." curl -s http://localhost:4566/_localstack/health | head -10 || echo "LocalStack health check failed" # Check if LocalStack container is running docker ps | grep localstack || echo "No LocalStack container found" # Show LocalStack container network info docker ps --format "{{.Names}}" | grep -i localstack | head -1 | xargs -I {} docker inspect {} --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' || echo "Could not get LocalStack IP" - name: Create S3 bucket for tests (host LocalStack) run: | awslocal s3 mb s3://$AWS_STACK_NAME || true awslocal s3 ls - name: Create k3s cluster (k3d) timeout-minutes: 5 run: | # Create cluster - host.k3d.internal will allow pods to access host services # No port mapping needed - LocalStack is on host, accessible via host.k3d.internal:4566 k3d cluster create unity-builder --agents 1 --wait kubectl config current-context | cat - name: Verify cluster readiness and LocalStack connectivity timeout-minutes: 2 run: | for i in {1..60}; do if kubectl get nodes 2>/dev/null | grep -q Ready; then echo "Cluster is ready" break fi echo "Waiting for cluster... ($i/60)" sleep 5 done kubectl get nodes kubectl get storageclass # Show node resources kubectl describe nodes | grep -A 5 "Allocated resources" || true # Test LocalStack connectivity from k3d cluster echo "Testing LocalStack connectivity from k3d cluster..." echo "From host (should work):" curl -s --max-time 5 http://localhost:4566/_localstack/health | head -5 || echo "Host connectivity failed" echo "From k3d cluster via host.k3d.internal:" kubectl run test-localstack --image=curlimages/curl --rm -i --restart=Never --timeout=10s -- \ curl -v --max-time 5 http://host.k3d.internal:4566/_localstack/health 2>&1 | head -20 || \ echo "Cluster connectivity test - if this fails, LocalStack may not be accessible from k3d" # Clean up disk space on the k3d node to prevent evictions echo "Cleaning up disk space on k3d nodes..." docker exec k3d-unity-builder-agent-0 sh -c "df -h && docker system prune -af --volumes || true" || true docker system prune -af --volumes || true # Clean up disk space on the node to prevent evictions echo "Cleaning up disk space on k3d nodes..." docker exec k3d-unity-builder-agent-0 sh -c "df -h && docker system prune -af --volumes || true" || true docker system prune -af --volumes || true - uses: actions/setup-node@v4 with: node-version: 20 cache: 'yarn' - name: Clean up disk space before tests run: | # Clean up any leftover cache files from previous runs rm -rf ./cloud-runner-cache/* || true # Clean up system caches and temporary files sudo apt-get clean || true docker system prune -f || true # Show available disk space df -h - run: yarn install --frozen-lockfile - name: Clean up K8s test resources run: | # Clean up K8s resources before each test (only test resources, not system pods) echo "Cleaning up K8s test resources..." # Only clean up resources in default namespace and resources matching our test patterns kubectl delete jobs --all --ignore-not-found=true -n default || true # Delete completed/failed pods in default namespace (not system pods) kubectl get pods -n default -o name 2>/dev/null | grep -E "(unity-builder-job-|helper-pod-)" | while read pod; do kubectl delete "$pod" --ignore-not-found=true || true done || true # Only delete PVCs that match our naming pattern (unity-builder-pvc-*) kubectl get pvc -n default -o name 2>/dev/null | grep "unity-builder-pvc-" | while read pvc; do kubectl delete "$pvc" --ignore-not-found=true || true done || true # Only delete secrets that match our naming pattern (build-credentials-*) kubectl get secrets -n default -o name 2>/dev/null | grep "build-credentials-" | while read secret; do kubectl delete "$secret" --ignore-not-found=true || true done || true sleep 3 # Clean up disk space - aggressive cleanup to prevent evictions rm -rf ./cloud-runner-cache/* || true docker system prune -af --volumes || true # Clean up disk space on k3d node to prevent ephemeral-storage evictions echo "Cleaning up disk space on k3d node..." docker exec k3d-unity-builder-agent-0 sh -c "docker system prune -af --volumes || true" 2>/dev/null || true docker exec k3d-unity-builder-agent-0 sh -c "df -h" 2>/dev/null || true - name: Run cloud-runner-end2end-caching test timeout-minutes: 60 run: yarn run test "cloud-runner-end2end-caching" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: k8s # Set resource requests for tests - increased memory to prevent OOM kills containerCpu: '1000' containerMemory: '1024' AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_S3_ENDPOINT: http://localhost:4566 AWS_ENDPOINT: http://localhost:4566 INPUT_AWSS3ENDPOINT: http://localhost:4566 INPUT_AWSENDPOINT: http://localhost:4566 AWS_S3_FORCE_PATH_STYLE: 'true' AWS_EC2_METADATA_DISABLED: 'true' GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up K8s test resources run: | kubectl delete jobs --all --ignore-not-found=true -n default || true kubectl get pods -n default -o name 2>/dev/null | grep -E "(unity-builder-job-|helper-pod-)" | while read pod; do kubectl delete "$pod" --ignore-not-found=true || true done || true kubectl get pvc -n default -o name 2>/dev/null | grep "unity-builder-pvc-" | while read pvc; do kubectl delete "$pvc" --ignore-not-found=true || true done || true kubectl get secrets -n default -o name 2>/dev/null | grep "build-credentials-" | while read secret; do kubectl delete "$secret" --ignore-not-found=true || true done || true sleep 3 rm -rf ./cloud-runner-cache/* || true docker system prune -f || true - name: Run cloud-runner-end2end-retaining test timeout-minutes: 60 run: yarn run test "cloud-runner-end2end-retaining" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: k8s containerCpu: '512' containerMemory: '512' AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_S3_ENDPOINT: http://localhost:4566 AWS_ENDPOINT: http://localhost:4566 INPUT_AWSS3ENDPOINT: http://localhost:4566 INPUT_AWSENDPOINT: http://localhost:4566 AWS_S3_FORCE_PATH_STYLE: 'true' AWS_EC2_METADATA_DISABLED: 'true' GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up K8s test resources run: | kubectl delete jobs --all --ignore-not-found=true -n default || true kubectl get pods -n default -o name 2>/dev/null | grep -E "(unity-builder-job-|helper-pod-)" | while read pod; do kubectl delete "$pod" --ignore-not-found=true || true done || true kubectl get pvc -n default -o name 2>/dev/null | grep "unity-builder-pvc-" | while read pvc; do kubectl delete "$pvc" --ignore-not-found=true || true done || true kubectl get secrets -n default -o name 2>/dev/null | grep "build-credentials-" | while read secret; do kubectl delete "$secret" --ignore-not-found=true || true done || true sleep 3 rm -rf ./cloud-runner-cache/* || true docker system prune -f || true - name: Run cloud-runner-hooks test timeout-minutes: 60 run: yarn run test "cloud-runner-hooks" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: k8s containerCpu: '512' containerMemory: '512' AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_S3_ENDPOINT: http://localhost:4566 AWS_ENDPOINT: http://localhost:4566 INPUT_AWSS3ENDPOINT: http://localhost:4566 INPUT_AWSENDPOINT: http://localhost:4566 AWS_S3_FORCE_PATH_STYLE: 'true' AWS_EC2_METADATA_DISABLED: 'true' GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} localstack: name: Cloud Runner Tests (LocalStack) runs-on: ubuntu-latest services: localstack: image: localstack/localstack ports: - 4566:4566 env: SERVICES: cloudformation,ecs,kinesis,cloudwatch,s3,logs steps: - uses: actions/checkout@v4 with: lfs: false - uses: actions/setup-node@v4 with: node-version: 20 cache: 'yarn' - name: Clean up disk space before tests run: | # Clean up any leftover cache files from previous runs rm -rf ./cloud-runner-cache/* || true # Clean up system caches and temporary files sudo apt-get clean || true docker system prune -f || true # Show available disk space df -h - run: yarn install --frozen-lockfile - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-end2end-locking test timeout-minutes: 60 run: yarn run test "cloud-runner-end2end-locking" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-end2end-caching test timeout-minutes: 60 run: yarn run test "cloud-runner-end2end-caching" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-end2end-retaining test timeout-minutes: 60 run: yarn run test "cloud-runner-end2end-retaining" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-caching test timeout-minutes: 60 run: yarn run test "cloud-runner-caching" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-environment test timeout-minutes: 60 run: yarn run test "cloud-runner-environment" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-image test timeout-minutes: 60 run: yarn run test "cloud-runner-image" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-hooks test timeout-minutes: 60 run: yarn run test "cloud-runner-hooks" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-local-persistence test timeout-minutes: 60 run: yarn run test "cloud-runner-local-persistence" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-locking-core test timeout-minutes: 60 run: yarn run test "cloud-runner-locking-core" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} - name: Clean up disk space run: | rm -rf ./cloud-runner-cache/* || true docker system prune -f || true df -h - name: Run cloud-runner-locking-get-locked test timeout-minutes: 60 run: yarn run test "cloud-runner-locking-get-locked" --detectOpenHandles --forceExit --runInBand env: UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} PROJECT_PATH: test-project TARGET_PLATFORM: StandaloneWindows64 cloudRunnerTests: true versioning: None KUBE_STORAGE_CLASS: local-path PROVIDER_STRATEGY: aws AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_ENDPOINT: http://localhost:4566 AWS_ENDPOINT_URL: http://localhost:4566 GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} # Commented out: Using LocalStack tests instead of real AWS # aws: # name: Cloud Runner Tests (AWS) # runs-on: ubuntu-latest # needs: [k8s, localstack] # strategy: # fail-fast: false # matrix: # test: # - 'cloud-runner-end2end-caching' # - 'cloud-runner-end2end-retaining' # - 'cloud-runner-hooks' # steps: # - uses: actions/checkout@v4 # with: # lfs: false # - name: Configure AWS Credentials # uses: aws-actions/configure-aws-credentials@v1 # with: # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # aws-region: ${{ env.AWS_REGION }} # - uses: actions/setup-node@v4 # with: # node-version: 20 # cache: 'yarn' # - run: yarn install --frozen-lockfile # - run: yarn run test "${{ matrix.test }}" --detectOpenHandles --forceExit --runInBand # timeout-minutes: 60 # env: # UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} # UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} # UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} # PROJECT_PATH: test-project # TARGET_PLATFORM: StandaloneWindows64 # cloudRunnerTests: true # versioning: None # PROVIDER_STRATEGY: aws # AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} # AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # GIT_PRIVATE_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }} # GITHUB_TOKEN: ${{ secrets.GIT_PRIVATE_TOKEN }}