From eca54d70f04b17a1d6e6f2e37ab9a7a1c688908c Mon Sep 17 00:00:00 2001 From: Randolph Settgast Date: Tue, 28 Jul 2026 22:04:56 -0700 Subject: [PATCH 1/3] Revert "fix assignement check (#4046)" This reverts commit e971774095ed4d5a0477c685b4f222fc2990a464. --- .github/workflows/ci_tests.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 133949c5e1e..78aab6f54c1 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -267,15 +267,11 @@ jobs: steps: - name: If this is a PR, Check that it is assigned env: - GITHUB_TOKEN: ${{ github.token }} + PR_JSON: ${{ toJson(github.event.pull_request) }} run: | set -euo pipefail if [[ "${{ github.event_name }}" != 'pull_request' ]]; then exit 0 ; fi - PR_JSON=$(curl --fail --silent --show-error \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${GITHUB_TOKEN}" \ - https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.number }}) NUM_ASSIGNEES=$(jq -r '.assignees | length' <<< "${PR_JSON}") echo "There are ${NUM_ASSIGNEES} assignees on this PR." if [[ "${NUM_ASSIGNEES}" == 0 ]]; then exit 1 ; fi From 2ee0b995c3c3597ad6f85a3f8e7fe2084bafadbd Mon Sep 17 00:00:00 2001 From: Randolph Settgast Date: Tue, 28 Jul 2026 22:05:18 -0700 Subject: [PATCH 2/3] Revert "reanable sccache using a legacy backup that uses existing GCP secret (#4045)" This reverts commit 10ade7d1378a055390276a9d1fa40582aad9d2ad. --- .github/workflows/build_and_test.yml | 82 +++++++++-------------- scripts/ci_build_and_test_in_container.sh | 9 +-- 2 files changed, 32 insertions(+), 59 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index f4fda44ef75..847175193ff 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -212,7 +212,6 @@ jobs: LEGACY_SCCACHE_ENDPOINT: ${{ secrets.SCCACHE_ENDPOINT }} LEGACY_CLOUDFLARE_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }} LEGACY_CLOUDFLARE_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }} - LEGACY_GOOGLE_CLOUD_GCP: ${{ secrets.GOOGLE_CLOUD_GCP }} run: | set -euo pipefail @@ -259,9 +258,7 @@ jobs: selected_sccache_config_toml="${DIRECT_SCCACHE_CONFIG_TOML:-}" selected_sccache_env_vars_json="${direct_sccache_env_vars_json}" selected_sccache_files_json="${direct_sccache_files_json}" - fi - - if [[ -z "${selected_sccache_config_toml:-}" && -z "${selected_sccache_env_vars_json:-}" && -z "${selected_sccache_files_json:-}" && -n "${SCCACHE_PROFILES_JSON:-}" && -n "${sccache_profile}" ]]; then + elif [[ -n "${SCCACHE_PROFILES_JSON:-}" && -n "${sccache_profile}" ]]; then sccache_profiles_json="$(validate_optional_json_object "SCCACHE_PROFILES_JSON" "${SCCACHE_PROFILES_JSON}")" selected_profile_json="$(jq -c --arg profile "${sccache_profile}" '.[$profile] // empty' <<< "${sccache_profiles_json}")" @@ -271,42 +268,23 @@ jobs: selected_sccache_env_vars_json="$(jq -c '.env_vars // {}' <<< "${selected_profile_json}")" selected_sccache_files_json="$(jq -c '.files // {}' <<< "${selected_profile_json}")" fi - fi - - if [[ -z "${selected_sccache_config_toml:-}" && -z "${selected_sccache_env_vars_json:-}" && -z "${selected_sccache_files_json:-}" ]]; then - # Temporary compatibility for orgs that still use pre-profile - # sccache secrets. Prefer SCCACHE_PROFILES_JSON for new setup. - case "${sccache_profile}" in - cloudflare) - if [[ -n "${LEGACY_SCCACHE_BUCKET:-}" && -n "${LEGACY_SCCACHE_ENDPOINT:-}" && -n "${LEGACY_CLOUDFLARE_R2_ACCESS_KEY_ID:-}" && -n "${LEGACY_CLOUDFLARE_R2_SECRET_ACCESS_KEY:-}" ]]; then - selected_sccache_env_vars_json="$(jq -cn \ - --arg bucket "${LEGACY_SCCACHE_BUCKET}" \ - --arg access_key_id "${LEGACY_CLOUDFLARE_R2_ACCESS_KEY_ID}" \ - --arg secret_access_key "${LEGACY_CLOUDFLARE_R2_SECRET_ACCESS_KEY}" \ - --arg endpoint "${LEGACY_SCCACHE_ENDPOINT}" \ - '{ - SCCACHE_BUCKET: $bucket, - AWS_ACCESS_KEY_ID: $access_key_id, - AWS_SECRET_ACCESS_KEY: $secret_access_key, - SCCACHE_ENDPOINT: $endpoint, - SCCACHE_S3_USE_SSL: "true", - SCCACHE_REGION: "auto" - }' - )" - fi - ;; - gcp) - if [[ -n "${LEGACY_GOOGLE_CLOUD_GCP:-}" ]]; then - selected_sccache_config_toml="$(printf '%s\n' \ - '[cache.gcs]' \ - 'rw_mode = "READ_WRITE"' \ - 'cred_path = "/tmp/geos/.sccache-runtime/gcp-service-account.json"' \ - 'bucket = "geos-dev"' \ - 'key_prefix = "sccache"')" - selected_sccache_files_json="$(jq -cn --arg credentials "${LEGACY_GOOGLE_CLOUD_GCP}" '{"gcp-service-account.json": $credentials}')" - fi - ;; - esac + elif [[ "${sccache_profile}" == "cloudflare" ]]; then + if [[ -n "${LEGACY_SCCACHE_BUCKET:-}" && -n "${LEGACY_SCCACHE_ENDPOINT:-}" && -n "${LEGACY_CLOUDFLARE_R2_ACCESS_KEY_ID:-}" && -n "${LEGACY_CLOUDFLARE_R2_SECRET_ACCESS_KEY:-}" ]]; then + selected_sccache_env_vars_json="$(jq -cn \ + --arg bucket "${LEGACY_SCCACHE_BUCKET}" \ + --arg access_key_id "${LEGACY_CLOUDFLARE_R2_ACCESS_KEY_ID}" \ + --arg secret_access_key "${LEGACY_CLOUDFLARE_R2_SECRET_ACCESS_KEY}" \ + --arg endpoint "${LEGACY_SCCACHE_ENDPOINT}" \ + '{ + SCCACHE_BUCKET: $bucket, + AWS_ACCESS_KEY_ID: $access_key_id, + AWS_SECRET_ACCESS_KEY: $secret_access_key, + SCCACHE_ENDPOINT: $endpoint, + SCCACHE_S3_USE_SSL: "true", + SCCACHE_REGION: "auto" + }' + )" + fi fi if [[ "${selected_sccache_env_vars_json:-}" == "{}" ]]; then @@ -855,17 +833,6 @@ jobs: REQUESTS_CA_BUNDLE: /etc/pki/tls/certs/ca-bundle.crt CURL_CA_BUNDLE: /etc/pki/tls/certs/ca-bundle.crt - - name: Show sccache stats - if: ${{ always() && steps.sccache_config.outputs.use_sccache == 'true' }} - run: | - sccache_runtime_dir="${{ steps.sccache_config.outputs.sccache_runtime_dir }}" - sccache_stats_file="${GITHUB_WORKSPACE}/${sccache_runtime_dir}/stats.txt" - if [[ -n "${sccache_runtime_dir}" && -f "${sccache_stats_file}" ]]; then - cat "${sccache_stats_file}" - else - echo "No in-container sccache stats file was captured." - fi - - name: 'Cleanup build folder' if: always() run: | @@ -874,3 +841,16 @@ jobs: -v "${GITHUB_WORKSPACE}:/tmp/geos" \ alpine:3.20 \ sh -lc 'rm -rf /tmp/geos/* /tmp/geos/.[!.]* /tmp/geos/..?* || true' + + - name: Show sccache stats + if: ${{ always() && steps.sccache_config.outputs.use_sccache == 'true' }} + run: | + sccache_env_file="${{ steps.sccache_config.outputs.sccache_env_file }}" + if [[ -n "${sccache_env_file}" && -f "${GITHUB_WORKSPACE}/${sccache_env_file}" ]]; then + while IFS='=' read -r key value || [[ -n "${key}" ]]; do + [[ -z "${key}" ]] && continue + export "${key}=${value}" + done < "${GITHUB_WORKSPACE}/${sccache_env_file}" + fi + + command -v sccache >/dev/null && sccache --show-stats || true diff --git a/scripts/ci_build_and_test_in_container.sh b/scripts/ci_build_and_test_in_container.sh index 2709ae3dbaf..81193ce3b4d 100755 --- a/scripts/ci_build_and_test_in_container.sh +++ b/scripts/ci_build_and_test_in_container.sh @@ -467,14 +467,7 @@ phase_finish 0 if [[ -n "${SCCACHE_BIN}" ]]; then echo "sccache post-build state" - SCCACHE_STATS_FILE="${GEOS_SRC_DIR}/.sccache-runtime/stats.txt" - or_die mkdir -p "$(dirname "${SCCACHE_STATS_FILE}")" - ${SCCACHE_BIN} --show-adv-stats | tee "${SCCACHE_STATS_FILE}" - SCCACHE_STATS_STATUS=${PIPESTATUS[0]} - if [[ ${SCCACHE_STATS_STATUS} != 0 ]]; then - echo ERROR ${SCCACHE_STATS_STATUS} command: ${SCCACHE_BIN} --show-adv-stats - exit ${SCCACHE_STATS_STATUS} - fi + or_die ${SCCACHE_BIN} --show-adv-stats fi if [[ "${CODE_COVERAGE}" = true ]]; then From 89f3f4e80b1f9b8b2ab9daad7cce48cec8bd0a35 Mon Sep 17 00:00:00 2001 From: Randolph Settgast Date: Tue, 28 Jul 2026 22:13:19 -0700 Subject: [PATCH 3/3] Revert "allow for forks in different orgs to have different CI specifications (#4032)" This reverts commit 0139435c8222a007d988585c040979e9c399ad2b. Preserve later CI image, CUDA, and CTest changes from #4043, code-rules checking from #3914, current action versions, authenticated live label checks, direct draft checks, and removal of environment dumps. --- .github/ci/README.md | 106 ----- .github/ci/orgs/EarthFlowAI.json | 16 - .github/ci/orgs/GEOS-DEV.json | 16 - .github/ci/providers/cloudflare.json | 5 - .github/ci/providers/gcp.json | 5 - .github/workflows/build_and_test.yml | 542 ++-------------------- .github/workflows/ci_tests.yml | 275 ++--------- scripts/ci_build_and_test_in_container.sh | 205 ++------ 8 files changed, 116 insertions(+), 1054 deletions(-) delete mode 100644 .github/ci/README.md delete mode 100644 .github/ci/orgs/EarthFlowAI.json delete mode 100644 .github/ci/orgs/GEOS-DEV.json delete mode 100644 .github/ci/providers/cloudflare.json delete mode 100644 .github/ci/providers/gcp.json diff --git a/.github/ci/README.md b/.github/ci/README.md deleted file mode 100644 index 6b37d03012c..00000000000 --- a/.github/ci/README.md +++ /dev/null @@ -1,106 +0,0 @@ -This directory contains runtime CI configuration consumed by `.github/workflows/ci_tests.yml`. - -Two checked-in files drive behavior for each CI run: - -1. `.github/ci/orgs/.json` — per-organization choices (which provider, which runners, etc.). -2. `.github/ci/providers/.json` — the shell commands and URI scheme for that - provider. Reused by any org that selects this provider. - -Every field in both files is required. There are no defaults: the full behavior of a CI run is -always visible by reading these two JSON files and nothing else. - -## Org files (`.github/ci/orgs/.json`) - -`` matches `github.repository_owner`. The resolver also checks the lowercase form of the -owner name. Each file contains the config entry for that org directly; there is no top-level -wrapper keyed by the org name. - -Required fields (all of them, always): - -- `storage_provider` - Name of a file under `.github/ci/providers/`. Must match `^[A-Za-z0-9_-]+$`. Selects the upload - CLI and URI scheme. - -- `sccache_profile` - Name of the sccache profile to pull from the inherited `SCCACHE_PROFILES_JSON` secret. Does not - need to match `storage_provider`, though it typically does. - -- `integrated_tests_artifact_bucket_path` - Path under the bucket where integrated-test artifacts are uploaded. For providers whose URI - scheme is `:///`, the first path segment is the bucket name. - -- `artifact_public_url_base` - Public URL root for uploaded artifacts. The consumer builds each final URL as - `${artifact_public_url_base}/${integrated_tests_artifact_bucket_path}/${filename}`, so the base - must already include any bucket/host prefix required for a valid public URL. For GCS this is - typically `https://storage.googleapis.com`. For Cloudflare R2 public dev URLs it is the - `https://pub-.r2.dev` domain for the bucket. - -- `artifact_public_url_bucket_scoped` - Boolean. Set `true` when `artifact_public_url_base` is rooted *inside* a specific bucket and - cannot traverse up to the account root (e.g. Cloudflare R2 public dev URLs of the form - `https://pub-.r2.dev`, which always resolve to one bucket). With the flag set, the - consumer strips the first path segment (the bucket name) from - `integrated_tests_artifact_bucket_path` before appending it to the base, so a base of - `https://pub-.r2.dev` and a path of `geosx/integratedTests` yields - `https://pub-.r2.dev/integratedTests/...` rather than doubling the bucket. Set `false` - for providers whose public root sits above the bucket (GCS, custom domains mapped to the - account, etc.). - -- `runner_ca_bundle_host_paths` - Map keyed by runner label, not by workflow role. Each value is a host-side certificate bundle - path to bind into the container as `/certs/ca-bundle.crt`. - Example: `{"streak2": "/etc/pki/tls/certs/ca-bundle.crt"}`. - The resolver first looks for an exact runner-label match. If none is found, it falls back to - the prefix before the first `-`, so a runner label like `streak2-32core` will reuse the - `streak2` entry. Use `{}` for runners that do not need an LLNL-style outbound cert bundle. - -- `runner_cuda_architectures` - Map keyed by runner label, not by workflow role. Each value is forwarded to CMake as - `CMAKE_CUDA_ARCHITECTURES` for CUDA jobs on that runner. The same exact-match then prefix - fallback used by `runner_ca_bundle_host_paths` applies. Example: `{"streak2": "86"}`. - -- `runners` - Map from runner role to runner label. Required roles: - - `default` - - `cpu_heavy` - - `integrated_tests` - - `code_coverage` - - `cuda` - - Each value is a single runner label string, e.g. `"ubuntu-22.04"` or `"streak2"`. - -## Provider files (`.github/ci/providers/.json`) - -Required fields (all of them, always): - -- `artifact_upload_command` - Shell command that uploads a single file. `$UPLOAD_SRC` and `$UPLOAD_DST` are exported by the - consumer before execution. The string is passed to `eval` — see the Security section below. - -- `artifact_upload_pre_command` - Shell command that runs once per job before the first upload, typically to authenticate the - CLI and validate credentials. `$ARTIFACT_UPLOAD_CREDENTIALS_FILE` is exported by the consumer. - The string is passed to `eval`. - -- `artifact_upload_uri_root` - URI scheme prefix the upload CLI expects, e.g. `"gs://"` or `"s3://"`. The consumer composes - `${artifact_upload_uri_root}${integrated_tests_artifact_bucket_path}/${filename}` as - `$UPLOAD_DST`. - -## Security - -The `artifact_upload_command` and `artifact_upload_pre_command` strings in every provider file -are passed to `eval` on the runner at upload time. They are executable shell, not inert -configuration. A change to those strings is a change to code that runs with the job's -environment — including credentials files, sccache tokens, and on self-hosted runners, the -runner host itself. - -Review edits to `.github/ci/providers/*.json` with the same scrutiny you would apply to a -workflow YAML change. Never populate these strings from PR- or user-controllable sources. - -## Secrets - -Secret payloads (artifact upload credentials, sccache config) are supplied through GitHub -repo/org secrets and consumed in the reusable workflow. They are not part of the JSON files -described here. diff --git a/.github/ci/orgs/EarthFlowAI.json b/.github/ci/orgs/EarthFlowAI.json deleted file mode 100644 index d3653a97192..00000000000 --- a/.github/ci/orgs/EarthFlowAI.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "storage_provider": "cloudflare", - "sccache_profile": "cloudflare", - "integrated_tests_artifact_bucket_path": "geosx/integratedTests", - "artifact_public_url_base": "https://pub-17b272fb651e459ca81dd0fd457099ed.r2.dev", - "artifact_public_url_bucket_scoped": true, - "runner_ca_bundle_host_paths": {}, - "runner_cuda_architectures": { "thinkpad": "120" }, - "runners": { - "default": "ubuntu-22.04", - "cpu_heavy": "32core", - "integrated_tests": "32core", - "code_coverage": "32core", - "cuda": "thinkpad" - } -} diff --git a/.github/ci/orgs/GEOS-DEV.json b/.github/ci/orgs/GEOS-DEV.json deleted file mode 100644 index 9ad891e74a0..00000000000 --- a/.github/ci/orgs/GEOS-DEV.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "storage_provider": "gcp", - "sccache_profile": "gcp", - "integrated_tests_artifact_bucket_path": "geosx/integratedTests", - "artifact_public_url_base": "https://storage.googleapis.com", - "artifact_public_url_bucket_scoped": false, - "runner_ca_bundle_host_paths": { "streak2": "/etc/pki/tls/certs/ca-bundle.crt" }, - "runner_cuda_architectures": { "streak2": "86" }, - "runners": { - "default": "ubuntu-22.04", - "cpu_heavy": "streak2", - "integrated_tests": "streak2-32core", - "code_coverage": "streak2", - "cuda": "streak2" - } -} diff --git a/.github/ci/providers/cloudflare.json b/.github/ci/providers/cloudflare.json deleted file mode 100644 index 8aa8f4ceb8f..00000000000 --- a/.github/ci/providers/cloudflare.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "artifact_upload_command": "aws s3 cp --only-show-errors \"$UPLOAD_SRC\" \"$UPLOAD_DST\" --endpoint-url \"$ARTIFACT_UPLOAD_ENDPOINT\"", - "artifact_upload_pre_command": "if [[ -z \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\" || ! -f \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\" ]]; then echo \"ARTIFACT_UPLOAD_CREDENTIALS_FILE is required when artifact upload is enabled.\" >&2; exit 1; fi; if ! command -v aws >/dev/null; then echo \"aws CLI is required for cloudflare artifact upload backend.\" >&2; exit 1; fi; if ! jq -e \"type == \\\"object\\\"\" \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\" >/dev/null 2>&1; then echo \"::error::Invalid JSON object in artifact upload credentials file.\" >&2; exit 1; fi; ACCESS_KEY_ID=\"$(jq -er \".access_key_id // empty\" \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\")\"; SECRET_ACCESS_KEY=\"$(jq -er \".secret_access_key // empty\" \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\")\"; ENDPOINT=\"$(jq -er \".endpoint // empty\" \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\")\"; if [[ -z \"$ACCESS_KEY_ID\" || -z \"$SECRET_ACCESS_KEY\" || -z \"$ENDPOINT\" ]]; then echo \"::error::Cloudflare artifact upload credentials must include access_key_id, secret_access_key, and endpoint.\" >&2; exit 1; fi; export AWS_ACCESS_KEY_ID=\"$ACCESS_KEY_ID\"; export AWS_SECRET_ACCESS_KEY=\"$SECRET_ACCESS_KEY\"; export AWS_DEFAULT_REGION=\"${AWS_DEFAULT_REGION:-auto}\"; export AWS_EC2_METADATA_DISABLED=true; export ARTIFACT_UPLOAD_ENDPOINT=\"$ENDPOINT\"", - "artifact_upload_uri_root": "s3://" -} diff --git a/.github/ci/providers/gcp.json b/.github/ci/providers/gcp.json deleted file mode 100644 index 9a1b617db60..00000000000 --- a/.github/ci/providers/gcp.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "artifact_upload_command": "CLOUDSDK_PYTHON=python3 gcloud storage cp --quiet -a publicRead \"$UPLOAD_SRC\" \"$UPLOAD_DST\"", - "artifact_upload_pre_command": "if [[ -z \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\" || ! -f \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\" ]]; then echo \"ARTIFACT_UPLOAD_CREDENTIALS_FILE is required when artifact upload is enabled.\" >&2; exit 1; fi; if ! jq -e . \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\" >/dev/null 2>&1; then echo \"::error::Invalid JSON in artifact upload credentials file.\" >&2; exit 1; fi; CLOUDSDK_PYTHON=python3 gcloud auth activate-service-account --key-file \"$ARTIFACT_UPLOAD_CREDENTIALS_FILE\"; CLOUDSDK_PYTHON=python3 gcloud config set storage/parallel_composite_upload_enabled True", - "artifact_upload_uri_root": "gs://" -} diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 847175193ff..4374601ae5b 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -37,10 +37,6 @@ on: DOCKER_RUN_ARGS: required: false type: string - DOCKER_CA_BUNDLE_HOST_PATH: - required: false - type: string - default: '' ENABLE_HYPRE: required: false type: string @@ -50,6 +46,9 @@ on: ENABLE_TRILINOS: required: false type: string + GCP_BUCKET: + required: false + type: string HOST_CONFIG: required: false type: string @@ -77,85 +76,14 @@ on: GEOS_ENABLE_BOUNDS_CHECK: required: false type: string - STORAGE_PROVIDER: - required: false - type: string - default: '' - SCCACHE_PROFILE: - required: false - type: string - default: '' - ARTIFACT_UPLOAD_BUCKET_PATH: - required: false - type: string - default: '' - ARTIFACT_UPLOAD_COMMAND: - required: false - type: string - default: '' - ARTIFACT_UPLOAD_PRE_COMMAND: - required: false - type: string - default: '' - ARTIFACT_UPLOAD_URI_ROOT: - required: false - type: string - default: '' - ARTIFACT_PUBLIC_URL_ROOT: - required: false - type: string - default: '' - ARTIFACT_PUBLIC_URL_BUCKET_SCOPED: - description: > - When "true", ARTIFACT_PUBLIC_URL_ROOT is treated as already rooted - inside the bucket (e.g. R2 public dev URLs of the form - https://pub-.r2.dev, which always resolve to one bucket). The - first path segment of ARTIFACT_UPLOAD_BUCKET_PATH (the bucket name) - is stripped before concatenation to avoid doubling up the bucket in - the final URL. Any value other than the literal string "true" is - treated as false. - required: false - type: string - default: '' - ARTIFACT_UPLOAD_URI_PREFIX: - required: false - type: string - default: '' - ARTIFACT_PUBLIC_URL_PREFIX: - required: false - type: string - default: '' secrets: - SCCACHE_CONFIG_TOML: - required: false - SCCACHE_ENV_VARS_JSON: - required: false - SCCACHE_FILES_JSON: - required: false - SCCACHE_PROFILES_JSON: - required: false - ARTIFACT_UPLOAD_CREDENTIALS_JSON: - required: false - ARTIFACT_PROVIDER_CREDENTIALS_JSON: + CODECOV_TOKEN: required: false GOOGLE_CLOUD_GCP: required: false - SCCACHE_BUCKET: - required: false - SCCACHE_ENDPOINT: - required: false - CLOUDFLARE_R2_ACCESS_KEY_ID: - required: false - CLOUDFLARE_R2_SECRET_ACCESS_KEY: - required: false - CODECOV_TOKEN: - required: false jobs: build_test_deploy: runs-on: ${{ inputs.RUNS_ON }} - defaults: - run: - shell: bash steps: - name: does_pr_have_necessary_labels if: ${{inputs.REQUIRED_LABEL && github.event_name == 'pull_request'}} @@ -198,342 +126,37 @@ jobs: lfs: ${{ inputs.BUILD_TYPE == 'integrated_tests' }} fetch-depth: 1 - - id: sccache_config - name: Resolve sccache configuration - env: - INPUT_USE_SCCACHE: ${{ inputs.USE_SCCACHE }} - INPUT_SCCACHE_PROFILE: ${{ inputs.SCCACHE_PROFILE }} - INPUT_STORAGE_PROVIDER: ${{ inputs.STORAGE_PROVIDER }} - DIRECT_SCCACHE_CONFIG_TOML: ${{ secrets.SCCACHE_CONFIG_TOML }} - DIRECT_SCCACHE_ENV_VARS_JSON: ${{ secrets.SCCACHE_ENV_VARS_JSON }} - DIRECT_SCCACHE_FILES_JSON: ${{ secrets.SCCACHE_FILES_JSON }} - SCCACHE_PROFILES_JSON: ${{ secrets.SCCACHE_PROFILES_JSON }} - LEGACY_SCCACHE_BUCKET: ${{ secrets.SCCACHE_BUCKET }} - LEGACY_SCCACHE_ENDPOINT: ${{ secrets.SCCACHE_ENDPOINT }} - LEGACY_CLOUDFLARE_R2_ACCESS_KEY_ID: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }} - LEGACY_CLOUDFLARE_R2_SECRET_ACCESS_KEY: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }} - run: | - set -euo pipefail - - validate_optional_json_object() { - local name="$1" - local json="${2:-}" - if [[ -z "${json}" ]]; then - printf '{}' - return 0 - fi - if ! jq -e 'type == "object"' <<< "${json}" >/dev/null 2>&1; then - echo "::error::Invalid JSON object in ${name}." >&2 - exit 1 - fi - printf '%s' "${json}" - } - - use_sccache=false - sccache_config_file= - sccache_env_file= - sccache_runtime_dir= - selected_sccache_config_toml= - selected_sccache_env_vars_json= - selected_sccache_files_json= - direct_sccache_env_vars_json= - direct_sccache_files_json= - - if [[ "${INPUT_USE_SCCACHE}" == "true" ]]; then - # Generic payload contract: - # - SCCACHE_CONFIG_TOML: literal TOML contents for ~/.config/sccache/config - # - SCCACHE_ENV_VARS_JSON: JSON object of {"ENV_VAR":"value"} - # - SCCACHE_FILES_JSON: JSON object of {"relative/path":"file-content"} - sccache_profile="${INPUT_SCCACHE_PROFILE:-${INPUT_STORAGE_PROVIDER}}" - - if [[ -n "${DIRECT_SCCACHE_ENV_VARS_JSON:-}" ]]; then - direct_sccache_env_vars_json="$(validate_optional_json_object "SCCACHE_ENV_VARS_JSON" "${DIRECT_SCCACHE_ENV_VARS_JSON}")" - fi - - if [[ -n "${DIRECT_SCCACHE_FILES_JSON:-}" ]]; then - direct_sccache_files_json="$(validate_optional_json_object "SCCACHE_FILES_JSON" "${DIRECT_SCCACHE_FILES_JSON}")" - fi - - if [[ -n "${DIRECT_SCCACHE_CONFIG_TOML:-}" || -n "${direct_sccache_env_vars_json}" || -n "${direct_sccache_files_json}" ]]; then - selected_sccache_config_toml="${DIRECT_SCCACHE_CONFIG_TOML:-}" - selected_sccache_env_vars_json="${direct_sccache_env_vars_json}" - selected_sccache_files_json="${direct_sccache_files_json}" - elif [[ -n "${SCCACHE_PROFILES_JSON:-}" && -n "${sccache_profile}" ]]; then - sccache_profiles_json="$(validate_optional_json_object "SCCACHE_PROFILES_JSON" "${SCCACHE_PROFILES_JSON}")" - - selected_profile_json="$(jq -c --arg profile "${sccache_profile}" '.[$profile] // empty' <<< "${sccache_profiles_json}")" - if [[ -n "${selected_profile_json}" ]]; then - selected_profile_json="$(validate_optional_json_object "SCCACHE_PROFILES_JSON[${sccache_profile}]" "${selected_profile_json}")" - selected_sccache_config_toml="$(jq -r '.config_toml // ""' <<< "${selected_profile_json}")" - selected_sccache_env_vars_json="$(jq -c '.env_vars // {}' <<< "${selected_profile_json}")" - selected_sccache_files_json="$(jq -c '.files // {}' <<< "${selected_profile_json}")" - fi - elif [[ "${sccache_profile}" == "cloudflare" ]]; then - if [[ -n "${LEGACY_SCCACHE_BUCKET:-}" && -n "${LEGACY_SCCACHE_ENDPOINT:-}" && -n "${LEGACY_CLOUDFLARE_R2_ACCESS_KEY_ID:-}" && -n "${LEGACY_CLOUDFLARE_R2_SECRET_ACCESS_KEY:-}" ]]; then - selected_sccache_env_vars_json="$(jq -cn \ - --arg bucket "${LEGACY_SCCACHE_BUCKET}" \ - --arg access_key_id "${LEGACY_CLOUDFLARE_R2_ACCESS_KEY_ID}" \ - --arg secret_access_key "${LEGACY_CLOUDFLARE_R2_SECRET_ACCESS_KEY}" \ - --arg endpoint "${LEGACY_SCCACHE_ENDPOINT}" \ - '{ - SCCACHE_BUCKET: $bucket, - AWS_ACCESS_KEY_ID: $access_key_id, - AWS_SECRET_ACCESS_KEY: $secret_access_key, - SCCACHE_ENDPOINT: $endpoint, - SCCACHE_S3_USE_SSL: "true", - SCCACHE_REGION: "auto" - }' - )" - fi - fi - - if [[ "${selected_sccache_env_vars_json:-}" == "{}" ]]; then - selected_sccache_env_vars_json= - fi - - if [[ "${selected_sccache_files_json:-}" == "{}" ]]; then - selected_sccache_files_json= - fi - - if [[ -z "${selected_sccache_config_toml:-}" && -z "${selected_sccache_env_vars_json:-}" && -z "${selected_sccache_files_json:-}" ]]; then - echo "::warning::USE_SCCACHE=true but no sccache payload was provided (direct SCCACHE_* secrets or a matching entry in SCCACHE_PROFILES_JSON). Disabling sccache for this run." - else - use_sccache=true - # Keep the runtime directory stable so profile JSON can refer to helper files - # using a fixed path inside the mounted repository. - sccache_runtime_dir=".sccache-runtime" - runtime_path="${GITHUB_WORKSPACE}/${sccache_runtime_dir}" - rm -rf "${runtime_path}" - mkdir -p "${runtime_path}" - - if [[ -n "${selected_sccache_config_toml:-}" ]]; then - sccache_config_file="${sccache_runtime_dir}/config.toml" - printf '%s' "${selected_sccache_config_toml}" > "${GITHUB_WORKSPACE}/${sccache_config_file}" - chmod 600 "${GITHUB_WORKSPACE}/${sccache_config_file}" - fi - - if [[ -n "${selected_sccache_env_vars_json:-}" ]]; then - selected_sccache_env_vars_json="$(validate_optional_json_object "selected sccache env vars" "${selected_sccache_env_vars_json}")" - - sccache_env_file="${sccache_runtime_dir}/env.list" - : > "${GITHUB_WORKSPACE}/${sccache_env_file}" - - while IFS=$'\t' read -r key value_b64; do - if [[ ! "${key}" =~ ^[A-Za-z_][A-Za-z0-9_]*$ ]]; then - echo "Invalid env var name in SCCACHE_ENV_VARS_JSON: ${key}" >&2 - exit 1 - fi - - value="$(printf '%s' "${value_b64}" | base64 --decode)" - if [[ "${value}" == *$'\n'* ]]; then - echo "Multiline env values are not supported in SCCACHE_ENV_VARS_JSON for key ${key}." >&2 - exit 1 - fi - - printf '%s=%s\n' "${key}" "${value}" >> "${GITHUB_WORKSPACE}/${sccache_env_file}" - done < <(jq -r 'to_entries[]? | [.key, (.value | tostring | @base64)] | @tsv' <<< "${selected_sccache_env_vars_json}") - - chmod 600 "${GITHUB_WORKSPACE}/${sccache_env_file}" - fi - - if [[ -n "${selected_sccache_files_json:-}" ]]; then - selected_sccache_files_json="$(validate_optional_json_object "selected sccache files" "${selected_sccache_files_json}")" - - while IFS=$'\t' read -r rel_path content_b64; do - if [[ ! "${rel_path}" =~ ^[A-Za-z0-9._/-]+$ ]] || [[ "${rel_path}" == /* ]] || [[ "${rel_path}" == *".."* ]]; then - echo "Invalid file path in SCCACHE_FILES_JSON: ${rel_path}" >&2 - exit 1 - fi - - file_path="${runtime_path}/${rel_path}" - mkdir -p "$(dirname "${file_path}")" - printf '%s' "${content_b64}" | base64 --decode > "${file_path}" - chmod 600 "${file_path}" - done < <(jq -r 'to_entries[]? | [.key, (.value | tostring | @base64)] | @tsv' <<< "${selected_sccache_files_json}") - fi - fi - fi - - { - echo "use_sccache=${use_sccache}" - echo "sccache_config_file=${sccache_config_file}" - echo "sccache_env_file=${sccache_env_file}" - echo "sccache_runtime_dir=${sccache_runtime_dir}" - } >> "$GITHUB_OUTPUT" + - id: 'auth' + if: ${{ inputs.GCP_BUCKET || inputs.USE_SCCACHE }} + uses: 'google-github-actions/auth@v2.1.10' + with: + credentials_json: '${{ secrets.GOOGLE_CLOUD_GCP }}' + create_credentials_file: true - - id: artifact_upload_credentials - name: Resolve artifact upload credentials - env: - INPUT_STORAGE_PROVIDER: ${{ inputs.STORAGE_PROVIDER }} - INPUT_ARTIFACT_UPLOAD_BUCKET_PATH: ${{ inputs.ARTIFACT_UPLOAD_BUCKET_PATH }} - DIRECT_ARTIFACT_UPLOAD_CREDENTIALS_JSON: ${{ secrets.ARTIFACT_UPLOAD_CREDENTIALS_JSON }} - ARTIFACT_PROVIDER_CREDENTIALS_JSON: ${{ secrets.ARTIFACT_PROVIDER_CREDENTIALS_JSON }} - LEGACY_GOOGLE_CLOUD_GCP: ${{ secrets.GOOGLE_CLOUD_GCP }} + - name: Prepare Codecov verification key + if: inputs.CODE_COVERAGE run: | - set -euo pipefail - - validate_optional_json() { - local name="$1" - local json="${2:-}" - if [[ -z "${json}" ]]; then - return 0 - fi - if ! jq -e . <<< "${json}" >/dev/null 2>&1; then - echo "::error::Invalid JSON in ${name}." >&2 - exit 1 - fi - } - - validate_optional_json_object() { - local name="$1" - local json="${2:-}" - if [[ -z "${json}" ]]; then - printf '{}' - return 0 - fi - if ! jq -e 'type == "object"' <<< "${json}" >/dev/null 2>&1; then - echo "::error::Invalid JSON object in ${name}." >&2 - exit 1 - fi - printf '%s' "${json}" - } - - credentials_file= - credentials_payload= - storage_provider="${INPUT_STORAGE_PROVIDER}" - provider_credentials_json= - - if [[ -n "${DIRECT_ARTIFACT_UPLOAD_CREDENTIALS_JSON:-}" ]]; then - validate_optional_json "ARTIFACT_UPLOAD_CREDENTIALS_JSON" "${DIRECT_ARTIFACT_UPLOAD_CREDENTIALS_JSON}" - credentials_payload="${DIRECT_ARTIFACT_UPLOAD_CREDENTIALS_JSON}" - fi - - if [[ -n "${INPUT_ARTIFACT_UPLOAD_BUCKET_PATH}" && -z "${credentials_payload}" && -n "${ARTIFACT_PROVIDER_CREDENTIALS_JSON:-}" && -n "${storage_provider}" ]]; then - provider_credentials_json="$(validate_optional_json_object "ARTIFACT_PROVIDER_CREDENTIALS_JSON" "${ARTIFACT_PROVIDER_CREDENTIALS_JSON}")" - - entry_type="$(jq -r --arg provider "${storage_provider}" '(.[$provider] // null) | type' <<< "${provider_credentials_json}")" - case "${entry_type}" in - string) - credentials_payload="$(jq -r --arg provider "${storage_provider}" '.[$provider]' <<< "${provider_credentials_json}")" - ;; - object|array) - credentials_payload="$(jq -c --arg provider "${storage_provider}" '.[$provider]' <<< "${provider_credentials_json}")" - ;; - null) - ;; - *) - echo "::error::Unsupported credential payload type '${entry_type}' for storage provider '${storage_provider}'." - exit 1 - ;; - esac - fi - - # Legacy GCP fallback: the repo historically provided a single - # GOOGLE_CLOUD_GCP service-account JSON secret. It is kept so existing - # orgs do not have to migrate immediately. No equivalent Cloudflare - # fallback exists: new Cloudflare setups must provide credentials via - # ARTIFACT_PROVIDER_CREDENTIALS_JSON (or ARTIFACT_UPLOAD_CREDENTIALS_JSON - # for one-off overrides). Reusing SCCACHE_ENDPOINT as the R2 artifact - # endpoint is incorrect whenever cache and artifact buckets diverge. - if [[ -n "${INPUT_ARTIFACT_UPLOAD_BUCKET_PATH}" && -z "${credentials_payload}" ]]; then - case "${storage_provider}" in - gcp) - credentials_payload="${LEGACY_GOOGLE_CLOUD_GCP:-}" - ;; - esac - fi - - if [[ -n "${INPUT_ARTIFACT_UPLOAD_BUCKET_PATH}" && -z "${credentials_payload}" ]]; then - echo "::error::No artifact upload credentials resolved for storage provider '${storage_provider}'. Set ARTIFACT_PROVIDER_CREDENTIALS_JSON (keyed by provider) or ARTIFACT_UPLOAD_CREDENTIALS_JSON for a one-off override." - exit 1 - fi - - if [[ -n "${credentials_payload}" ]]; then - validate_optional_json "resolved artifact upload credentials" "${credentials_payload}" - credentials_dir="${RUNNER_TEMP}/artifact-upload-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" - mkdir -p "${credentials_dir}" - credentials_file="${credentials_dir}/${storage_provider:-artifact}.json" - printf '%s' "${credentials_payload}" > "${credentials_file}" - chmod 600 "${credentials_file}" - fi - - echo "credentials_file=${credentials_file}" >> "$GITHUB_OUTPUT" - - - name: Print environment - run: printenv + set -euxo pipefail + GNUPGHOME="${RUNNER_TEMP}/codecov-gnupg" + export GNUPGHOME + mkdir -p "${GNUPGHOME}" + chmod 700 "${GNUPGHOME}" + gpg --batch --import "${GITHUB_WORKSPACE}/.github/codecov/verification.gpg.asc" || true + gpg --batch --list-keys 806BB28AED779869 >/dev/null + echo "GNUPGHOME=${GNUPGHOME}" >> "${GITHUB_ENV}" + + - name: 'Set up Cloud SDK' + if: inputs.GCP_BUCKET + uses: 'google-github-actions/setup-gcloud@v2.1.4' + with: + version: '>= 363.0.0' - name: Build, test, deploy. - env: - INPUT_DOCKER_CA_BUNDLE_HOST_PATH: ${{ inputs.DOCKER_CA_BUNDLE_HOST_PATH }} run: | # Those two bash arrays will be populated depending on the required options, # and expended as CLI arguments for the docker and scripts calls. docker_args=() script_args=() - HAS_DATA_EXCHANGE=false - HAS_UPLOAD_TARGET=false - DATA_BASENAME= - DATA_EXCHANGE_DIR= - STORAGE_PROVIDER="${{ inputs.STORAGE_PROVIDER }}" - ARTIFACT_UPLOAD_BUCKET_PATH="${{ inputs.ARTIFACT_UPLOAD_BUCKET_PATH }}" - ARTIFACT_UPLOAD_URI_ROOT="${{ inputs.ARTIFACT_UPLOAD_URI_ROOT }}" - ARTIFACT_PUBLIC_URL_ROOT="${{ inputs.ARTIFACT_PUBLIC_URL_ROOT }}" - ARTIFACT_PUBLIC_URL_BUCKET_SCOPED="${{ inputs.ARTIFACT_PUBLIC_URL_BUCKET_SCOPED }}" - ARTIFACT_UPLOAD_URI_PREFIX="${{ inputs.ARTIFACT_UPLOAD_URI_PREFIX }}" - ARTIFACT_PUBLIC_URL_PREFIX="${{ inputs.ARTIFACT_PUBLIC_URL_PREFIX }}" - ARTIFACT_UPLOAD_CREDENTIALS_FILE="${{ steps.artifact_upload_credentials.outputs.credentials_file }}" - ARTIFACT_UPLOAD_COMMAND="$(cat <<'__ARTIFACT_UPLOAD_COMMAND__' - ${{ inputs.ARTIFACT_UPLOAD_COMMAND }} - __ARTIFACT_UPLOAD_COMMAND__ - )" - ARTIFACT_UPLOAD_PRE_COMMAND="$(cat <<'__ARTIFACT_UPLOAD_PRE_COMMAND__' - ${{ inputs.ARTIFACT_UPLOAD_PRE_COMMAND }} - __ARTIFACT_UPLOAD_PRE_COMMAND__ - )" - - if [[ -z "${ARTIFACT_UPLOAD_URI_PREFIX}" && -n "${ARTIFACT_UPLOAD_BUCKET_PATH}" ]]; then - ARTIFACT_UPLOAD_URI_PREFIX="${ARTIFACT_UPLOAD_URI_ROOT%/}/${ARTIFACT_UPLOAD_BUCKET_PATH}" - fi - - # The org config's artifact_public_url_base (propagated as - # ARTIFACT_PUBLIC_URL_ROOT) must already be rooted wherever the bucket - # is publicly served from. We simply append the bucket path. - # - # Exception: when ARTIFACT_PUBLIC_URL_BUCKET_SCOPED=="true" the root is - # already rooted *inside* the bucket (e.g. R2 public dev URLs of the - # form https://pub-.r2.dev, which always resolve to one bucket). - # In that case the leading path segment of ARTIFACT_UPLOAD_BUCKET_PATH - # is the bucket name and must be stripped before concatenation, - # otherwise we would double up the bucket in the final URL. - if [[ -z "${ARTIFACT_PUBLIC_URL_PREFIX}" && -n "${ARTIFACT_PUBLIC_URL_ROOT}" ]]; then - if [[ -n "${ARTIFACT_UPLOAD_BUCKET_PATH}" ]]; then - PUBLIC_URL_BUCKET_PATH="${ARTIFACT_UPLOAD_BUCKET_PATH}" - if [[ "${ARTIFACT_PUBLIC_URL_BUCKET_SCOPED}" == "true" ]]; then - # Strip the first segment (the bucket name) and any leading slash. - PUBLIC_URL_BUCKET_PATH="${PUBLIC_URL_BUCKET_PATH#/}" - if [[ "${PUBLIC_URL_BUCKET_PATH}" == */* ]]; then - PUBLIC_URL_BUCKET_PATH="${PUBLIC_URL_BUCKET_PATH#*/}" - else - PUBLIC_URL_BUCKET_PATH='' - fi - fi - if [[ -n "${PUBLIC_URL_BUCKET_PATH}" ]]; then - ARTIFACT_PUBLIC_URL_PREFIX="${ARTIFACT_PUBLIC_URL_ROOT%/}/${PUBLIC_URL_BUCKET_PATH}" - else - ARTIFACT_PUBLIC_URL_PREFIX="${ARTIFACT_PUBLIC_URL_ROOT%/}" - fi - else - ARTIFACT_PUBLIC_URL_PREFIX="${ARTIFACT_PUBLIC_URL_ROOT%/}" - fi - fi - - if [[ -n "${ARTIFACT_UPLOAD_BUCKET_PATH}" || -n "${ARTIFACT_UPLOAD_URI_PREFIX}" || -n "${ARTIFACT_PUBLIC_URL_PREFIX}" ]]; then - if [[ -z "${ARTIFACT_UPLOAD_COMMAND}" || -z "${ARTIFACT_UPLOAD_URI_PREFIX}" ]]; then - echo "::error::ARTIFACT_UPLOAD_COMMAND and ARTIFACT_UPLOAD_URI_PREFIX must both be set when enabling artifact upload." - exit 1 - fi - HAS_UPLOAD_TARGET=true - fi if [[ -n "${{ inputs.NPROC }}" ]]; then NPROC=${{ inputs.NPROC }} @@ -546,29 +169,17 @@ jobs: docker_args+=(${{ inputs.DOCKER_RUN_ARGS }}) - if [[ -n "${INPUT_DOCKER_CA_BUNDLE_HOST_PATH}" ]]; then - if [[ ! -f "${INPUT_DOCKER_CA_BUNDLE_HOST_PATH}" ]]; then - echo "::error::Configured DOCKER_CA_BUNDLE_HOST_PATH does not exist: ${INPUT_DOCKER_CA_BUNDLE_HOST_PATH}" - exit 1 - fi - docker_args+=("--volume=${INPUT_DOCKER_CA_BUNDLE_HOST_PATH}:/certs/ca-bundle.crt:ro") - docker_args+=(-e SSL_CERT_FILE=/certs/ca-bundle.crt) - docker_args+=(-e REQUESTS_CA_BUNDLE=/certs/ca-bundle.crt) - docker_args+=(-e CURL_CA_BUNDLE=/certs/ca-bundle.crt) - fi - COMMIT=${{ github.event.pull_request.head.sha }} SHORT_COMMIT=${COMMIT:0:7} script_args+=(--install-dir-basename GEOS-${SHORT_COMMIT}) - if [[ "${{ inputs.BUILD_TYPE }}" == "integrated_tests" || "${HAS_UPLOAD_TARGET}" == "true" ]]; then - HAS_DATA_EXCHANGE=true - - if [[ "${{ inputs.BUILD_TYPE }}" == "integrated_tests" ]]; then + # All the data exchanged with the docker container is eventually meant to be sent to the cloud. + if [[ ! -z "${{ inputs.GCP_BUCKET }}" ]]; then + if [ "${{ inputs.BUILD_TYPE }}" = "build" ]; then + DATA_BASENAME=GEOS-and-TPL-${SHORT_COMMIT}.tar.gz + elif [ "${{ inputs.BUILD_TYPE }}" = "integrated_tests" ]; then DATA_BASENAME=integratedTests-pr${{ github.event.number }}-${{ github.run_number }}-${SHORT_COMMIT}.tar.gz script_args+=(--run-integrated-tests) - else - DATA_BASENAME=GEOS-and-TPL-${SHORT_COMMIT}.tar.gz fi script_args+=(--data-basename ${DATA_BASENAME}) @@ -585,22 +196,8 @@ jobs: HOST_CONFIG=${{ inputs.HOST_CONFIG }} script_args+=(${HOST_CONFIG:+"--host-config ${HOST_CONFIG}"}) - if [[ "${{ steps.sccache_config.outputs.use_sccache }}" == "true" ]]; then - script_args+=(--use-sccache) - - sccache_config_file="${{ steps.sccache_config.outputs.sccache_config_file }}" - if [[ -n "${sccache_config_file}" ]]; then - script_args+=(--sccache-config "${sccache_config_file}") - fi - - sccache_env_file="${{ steps.sccache_config.outputs.sccache_env_file }}" - if [[ -n "${sccache_env_file}" && -f "${GITHUB_WORKSPACE}/${sccache_env_file}" ]]; then - while IFS='=' read -r key value || [[ -n "${key}" ]]; do - [[ -z "${key}" ]] && continue - export "${key}=${value}" - docker_args+=(-e "${key}") - done < "${GITHUB_WORKSPACE}/${sccache_env_file}" - fi + if ${{ inputs.USE_SCCACHE }} == 'true'; then + script_args+=(--sccache-credentials $(basename ${GOOGLE_GHA_CREDS_PATH})) fi # We need to know where the code folder is mounted inside the container so we can run the script at the proper location! @@ -715,6 +312,8 @@ jobs: ${GITHUB_WORKSPACE_MOUNT_POINT}/scripts/ci_build_and_test_in_container.sh \ ${script_args[@]}" + # In case of integrated tests run, we still want to send the results to the cloud for inspection. + # While for standard build (if even possible), pushing a failed build would be pointless. # GHA set `-e` to bash scripts by default to fail asap, # but for this precise call, we want to deal with it more precisely set +e @@ -728,55 +327,24 @@ jobs: echo "Received exit status ${EXIT_STATUS} from the build process." set -e - artifact_upload_prepared=false - function upload_artifact () { - local source_file="$1" - local output_message="$2" - - if [[ "${HAS_UPLOAD_TARGET}" != "true" ]]; then - return 0 - fi - if [[ ! -f "${source_file}" ]]; then - return 0 - fi - - if [[ "${artifact_upload_prepared}" != "true" ]]; then - if [[ -n "${ARTIFACT_UPLOAD_PRE_COMMAND}" ]]; then - eval "${ARTIFACT_UPLOAD_PRE_COMMAND}" - fi - artifact_upload_prepared=true - fi - - artifact_name="$(basename "${source_file}")" - artifact_destination="${ARTIFACT_UPLOAD_URI_PREFIX%/}/${artifact_name}" - ( - set -euo pipefail - export UPLOAD_SRC="${source_file}" - export UPLOAD_DST="${artifact_destination}" - export ARTIFACT_UPLOAD_CREDENTIALS_FILE="${ARTIFACT_UPLOAD_CREDENTIALS_FILE}" - eval "${ARTIFACT_UPLOAD_COMMAND}" - ) - - if [[ -n "${ARTIFACT_PUBLIC_URL_PREFIX}" ]]; then - echo "${output_message} ${ARTIFACT_PUBLIC_URL_PREFIX%/}/${artifact_name}" - else - echo "${output_message} ${artifact_destination}" - fi - } - - if [[ "${HAS_DATA_EXCHANGE}" == "true" ]]; then + # Send to the bucket and print the download link when it makes sense. + if [[ ! -z "${{ inputs.GCP_BUCKET }}" ]]; then if [[ "${{ inputs.BUILD_TYPE }}" = "integrated_tests" || ${EXIT_STATUS} -eq 0 ]]; then - if [[ -f ${DATA_EXCHANGE_DIR}/${DATA_BASENAME} ]]; then - echo "Generated artifact at ${DATA_EXCHANGE_DIR}/${DATA_BASENAME}" - upload_artifact "${DATA_EXCHANGE_DIR}/${DATA_BASENAME}" "Download the bundle at" + # disable warning about parallel composite upload + CLOUDSDK_PYTHON=python3 gcloud config set storage/parallel_composite_upload_enabled True + + if [ -f ${DATA_EXCHANGE_DIR}/${DATA_BASENAME} ]; then + CLOUDSDK_PYTHON=python3 gcloud storage cp --quiet -a publicRead ${DATA_EXCHANGE_DIR}/${DATA_BASENAME} gs://${{ inputs.GCP_BUCKET }}/ + echo "Download the bundle at https://storage.googleapis.com/${{ inputs.GCP_BUCKET }}/${DATA_BASENAME}" fi if [ -f ${DATA_EXCHANGE_DIR}/test_logs_${DATA_BASENAME} ]; then - echo "Generated integrated test logs at ${DATA_EXCHANGE_DIR}/test_logs_${DATA_BASENAME}" - upload_artifact "${DATA_EXCHANGE_DIR}/test_logs_${DATA_BASENAME}" "Download integrated test logs here:" + CLOUDSDK_PYTHON=python3 gcloud storage cp --quiet -a publicRead ${DATA_EXCHANGE_DIR}/test_logs_${DATA_BASENAME} gs://${{ inputs.GCP_BUCKET }}/ + echo "Download integrated test logs here: https://storage.googleapis.com/${{ inputs.GCP_BUCKET }}/test_logs_${DATA_BASENAME}" fi if [ -f ${DATA_EXCHANGE_DIR}/baseline_${DATA_BASENAME} ];then + if [[ -n "${{ inputs.LOCAL_BASELINE_DIR }}" ]]; then # 1. We copy the baselines to a local directory to store them @@ -793,8 +361,9 @@ jobs: cp "${SOURCE_FILE}" "${TARGET_DIR}" fi - # 2. We push the baselines to cloud storage if an upload backend is configured. - upload_artifact "${DATA_EXCHANGE_DIR}/baseline_${DATA_BASENAME}" "Download test baselines here:" + # 2. We push the baselines to the cloud + CLOUDSDK_PYTHON=python3 gcloud storage cp --quiet -a publicRead ${DATA_EXCHANGE_DIR}/baseline_${DATA_BASENAME} gs://${{ inputs.GCP_BUCKET }}/ + echo "Download test baselines here: https://storage.googleapis.com/${{ inputs.GCP_BUCKET }}/baseline_${DATA_BASENAME}" echo "New baseline ID: baseline_${DATA_BASENAME::-7}" else echo "Baselines ${DATA_EXCHANGE_DIR}/baseline_${DATA_BASENAME} were not uploaded. Likeyly because no rebaseline was necessary." @@ -841,16 +410,3 @@ jobs: -v "${GITHUB_WORKSPACE}:/tmp/geos" \ alpine:3.20 \ sh -lc 'rm -rf /tmp/geos/* /tmp/geos/.[!.]* /tmp/geos/..?* || true' - - - name: Show sccache stats - if: ${{ always() && steps.sccache_config.outputs.use_sccache == 'true' }} - run: | - sccache_env_file="${{ steps.sccache_config.outputs.sccache_env_file }}" - if [[ -n "${sccache_env_file}" && -f "${GITHUB_WORKSPACE}/${sccache_env_file}" ]]; then - while IFS='=' read -r key value || [[ -n "${key}" ]]; do - [[ -z "${key}" ]] && continue - export "${key}=${value}" - done < "${GITHUB_WORKSPACE}/${sccache_env_file}" - fi - - command -v sccache >/dev/null && sccache --show-stats || true diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 78aab6f54c1..8faeb3a44cc 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -55,210 +55,6 @@ jobs: run: | echo "DOCKER_IMAGE_TAG=$(jq '.build.args.GEOS_TPL_TAG' -r .devcontainer/devcontainer.json)" >> "$GITHUB_OUTPUT" - # Resolve CI settings once and keep the build jobs declarative. - # - # Two checked-in files drive behavior: - # .github/ci/orgs/.json - # Per-org choices: storage provider name, sccache profile name, integrated-tests bucket - # path, public URL base and bucket-scoping, runner labels, and per-runner CA bundle paths. - # Every field is required; there are no defaults. See .github/ci/README.md for the schema. - # .github/ci/providers/.json - # Provider-level CLI details: the shell commands that upload artifacts and the URI scheme. - # Reused by any org that selects this provider. Every field is required. - # - # Provider payloads (credentials, sccache profiles) are supplied through inherited secrets: - # - SCCACHE_PROFILES_JSON - # - ARTIFACT_PROVIDER_CREDENTIALS_JSON - # Direct one-off overrides remain available in the reusable workflow via SCCACHE_* and - # ARTIFACT_UPLOAD_CREDENTIALS_JSON. - # - # SECURITY: the artifact_upload_command and artifact_upload_pre_command strings in each - # provider JSON file are passed to `eval` on the runner. A change to those strings is a - # change to executable shell, not a data-config tweak. Review edits to - # .github/ci/providers/*.json with the same scrutiny as workflow YAML. Do not populate - # those values from PR- or user-controllable sources. - resolve_ci_provider: - runs-on: ubuntu-22.04 - outputs: - STORAGE_PROVIDER: ${{ steps.resolve.outputs.STORAGE_PROVIDER }} - SCCACHE_PROFILE: ${{ steps.resolve.outputs.SCCACHE_PROFILE }} - INTEGRATED_TESTS_ARTIFACT_BUCKET_PATH: ${{ steps.resolve.outputs.INTEGRATED_TESTS_ARTIFACT_BUCKET_PATH }} - DOCKER_CA_BUNDLE_HOST_PATHS_JSON: ${{ steps.resolve.outputs.DOCKER_CA_BUNDLE_HOST_PATHS_JSON }} - CMAKE_CUDA_ARCHITECTURES_JSON: ${{ steps.resolve.outputs.CMAKE_CUDA_ARCHITECTURES_JSON }} - RUNNER_LABELS_JSON: ${{ steps.resolve.outputs.RUNNER_LABELS_JSON }} - ARTIFACT_UPLOAD_COMMAND: ${{ steps.resolve.outputs.ARTIFACT_UPLOAD_COMMAND }} - ARTIFACT_UPLOAD_PRE_COMMAND: ${{ steps.resolve.outputs.ARTIFACT_UPLOAD_PRE_COMMAND }} - ARTIFACT_UPLOAD_URI_ROOT: ${{ steps.resolve.outputs.ARTIFACT_UPLOAD_URI_ROOT }} - ARTIFACT_PUBLIC_URL_ROOT: ${{ steps.resolve.outputs.ARTIFACT_PUBLIC_URL_ROOT }} - ARTIFACT_PUBLIC_URL_BUCKET_SCOPED: ${{ steps.resolve.outputs.ARTIFACT_PUBLIC_URL_BUCKET_SCOPED }} - env: - CI_REPOSITORY_OWNER: ${{ github.repository_owner }} - steps: - - name: Checkout CI config - uses: actions/checkout@v6.0.3 - with: - sparse-checkout: | - .github/ci/orgs - .github/ci/providers - sparse-checkout-cone-mode: false - submodules: false - lfs: false - fetch-depth: 1 - - id: resolve - run: | - set -euo pipefail - - # --- Locate the org config file. Owners are matched case-insensitively. --- - REPOSITORY_OWNER_LOWER="$(printf '%s' "${CI_REPOSITORY_OWNER}" | tr '[:upper:]' '[:lower:]')" - ORG_CONFIG_PATH='' - for candidate in \ - "${GITHUB_WORKSPACE}/.github/ci/orgs/${CI_REPOSITORY_OWNER}.json" \ - "${GITHUB_WORKSPACE}/.github/ci/orgs/${REPOSITORY_OWNER_LOWER}.json" - do - if [[ -f "${candidate}" ]]; then - ORG_CONFIG_PATH="${candidate}" - break - fi - done - - if [[ -z "${ORG_CONFIG_PATH}" ]]; then - echo "::error::No CI organization config was found for repository owner '${CI_REPOSITORY_OWNER}'. Expected .github/ci/orgs/${CI_REPOSITORY_OWNER}.json or .github/ci/orgs/${REPOSITORY_OWNER_LOWER}.json." - exit 1 - fi - - if ! jq -e 'type == "object"' "${ORG_CONFIG_PATH}" >/dev/null; then - echo "::error::Invalid JSON object in ${ORG_CONFIG_PATH}." - exit 1 - fi - - ORG_CONFIG_JSON="$(jq -c . "${ORG_CONFIG_PATH}")" - - # --- Validate the full org schema. Every field is required; there are no defaults. --- - if ! jq -e ' - (.storage_provider | type == "string" and length > 0) - and (.sccache_profile | type == "string" and length > 0) - and (.integrated_tests_artifact_bucket_path | type == "string" and length > 0) - and (.artifact_public_url_base | type == "string") - and (.artifact_public_url_bucket_scoped | type == "boolean") - and (.runner_ca_bundle_host_paths | type == "object") - and (.runner_ca_bundle_host_paths | all(.[]; type == "string")) - and (.runner_cuda_architectures | type == "object") - and (.runner_cuda_architectures | all(.[]; type == "string" and length > 0)) - and (.runners | type == "object") - and (.runners.default | type == "string" and length > 0) - and (.runners.cpu_heavy | type == "string" and length > 0) - and (.runners.integrated_tests | type == "string" and length > 0) - and (.runners.code_coverage | type == "string" and length > 0) - and (.runners.cuda | type == "string" and length > 0) - ' <<< "${ORG_CONFIG_JSON}" >/dev/null; then - echo "::error::${ORG_CONFIG_PATH} must define every required field: storage_provider, sccache_profile, integrated_tests_artifact_bucket_path, artifact_public_url_base, artifact_public_url_bucket_scoped, runner_ca_bundle_host_paths, runner_cuda_architectures, and runners.{default,cpu_heavy,integrated_tests,code_coverage,cuda}. See .github/ci/README.md for the full schema." - exit 1 - fi - - # --- Extract org values. --- - STORAGE_PROVIDER="$(jq -r '.storage_provider' <<< "${ORG_CONFIG_JSON}")" - SCCACHE_PROFILE="$(jq -r '.sccache_profile' <<< "${ORG_CONFIG_JSON}")" - INTEGRATED_TESTS_ARTIFACT_BUCKET_PATH="$(jq -r '.integrated_tests_artifact_bucket_path' <<< "${ORG_CONFIG_JSON}")" - ARTIFACT_PUBLIC_URL_ROOT="$(jq -r '.artifact_public_url_base' <<< "${ORG_CONFIG_JSON}")" - ARTIFACT_PUBLIC_URL_BUCKET_SCOPED="$(jq -r '.artifact_public_url_bucket_scoped' <<< "${ORG_CONFIG_JSON}")" - RUNNER_LABELS_JSON="$(jq -c '.runners' <<< "${ORG_CONFIG_JSON}")" - RUNNER_CA_BUNDLE_HOST_PATHS_JSON="$(jq -c '.runner_ca_bundle_host_paths' <<< "${ORG_CONFIG_JSON}")" - RUNNER_CUDA_ARCHITECTURES_JSON="$(jq -c '.runner_cuda_architectures' <<< "${ORG_CONFIG_JSON}")" - - # --- Resolve per-runner-role CA bundle paths. --- - # Each runner role picks up the bundle path for its label; if no exact match, - # fall back to the prefix before the first '-' (so "streak2-32core" reuses "streak2"). - DOCKER_CA_BUNDLE_HOST_PATHS_JSON="$(jq -cn \ - --argjson runners "${RUNNER_LABELS_JSON}" \ - --argjson cert_paths "${RUNNER_CA_BUNDLE_HOST_PATHS_JSON}" ' - def resolve_path($runner_label): - ($cert_paths[$runner_label] - // (($runner_label | split("-")[0]) as $runner_prefix | $cert_paths[$runner_prefix]) - // ""); - { - default: resolve_path($runners.default), - cpu_heavy: resolve_path($runners.cpu_heavy), - integrated_tests: resolve_path($runners.integrated_tests), - code_coverage: resolve_path($runners.code_coverage), - cuda: resolve_path($runners.cuda) - }' - )" - - # --- Resolve CUDA architectures by runner role. --- - # Like CA bundle paths, CUDA architectures are keyed by runner label and use prefix fallback. - CMAKE_CUDA_ARCHITECTURES_JSON="$(jq -cn \ - --argjson runners "${RUNNER_LABELS_JSON}" \ - --argjson cuda_architectures "${RUNNER_CUDA_ARCHITECTURES_JSON}" ' - def resolve_arch($runner_label): - ($cuda_architectures[$runner_label] - // (($runner_label | split("-")[0]) as $runner_prefix | $cuda_architectures[$runner_prefix]) - // ""); - { - default: resolve_arch($runners.default), - cpu_heavy: resolve_arch($runners.cpu_heavy), - integrated_tests: resolve_arch($runners.integrated_tests), - code_coverage: resolve_arch($runners.code_coverage), - cuda: resolve_arch($runners.cuda) - }' - )" - - CUDA_RUNNER_LABEL="$(jq -r '.cuda' <<< "${RUNNER_LABELS_JSON}")" - if ! jq -e '.cuda | type == "string" and length > 0' <<< "${CMAKE_CUDA_ARCHITECTURES_JSON}" >/dev/null; then - echo "::error::${ORG_CONFIG_PATH} must define runner_cuda_architectures for CUDA runner '${CUDA_RUNNER_LABEL}'." - exit 1 - fi - - # --- Load and validate the provider file. --- - # storage_provider names a file under .github/ci/providers/. - # Restrict the allowed characters so the provider name cannot escape the directory. - if ! [[ "${STORAGE_PROVIDER}" =~ ^[A-Za-z0-9_-]+$ ]]; then - echo "::error::storage_provider '${STORAGE_PROVIDER}' contains disallowed characters. Allowed: letters, digits, '_', '-'." - exit 1 - fi - PROVIDER_CONFIG_PATH="${GITHUB_WORKSPACE}/.github/ci/providers/${STORAGE_PROVIDER}.json" - if [[ ! -f "${PROVIDER_CONFIG_PATH}" ]]; then - echo "::error::No provider config file at ${PROVIDER_CONFIG_PATH} for storage_provider '${STORAGE_PROVIDER}' (selected in ${ORG_CONFIG_PATH})." - exit 1 - fi - - if ! jq -e 'type == "object"' "${PROVIDER_CONFIG_PATH}" >/dev/null; then - echo "::error::Invalid JSON object in ${PROVIDER_CONFIG_PATH}." - exit 1 - fi - - PROVIDER_CONFIG_JSON="$(jq -c . "${PROVIDER_CONFIG_PATH}")" - - if ! jq -e ' - (.artifact_upload_command | type == "string" and length > 0) - and (.artifact_upload_pre_command | type == "string" and length > 0) - and (.artifact_upload_uri_root | type == "string" and length > 0) - ' <<< "${PROVIDER_CONFIG_JSON}" >/dev/null; then - echo "::error::${PROVIDER_CONFIG_PATH} must define artifact_upload_command, artifact_upload_pre_command, and artifact_upload_uri_root as non-empty strings." - exit 1 - fi - - ARTIFACT_UPLOAD_COMMAND="$(jq -r '.artifact_upload_command' <<< "${PROVIDER_CONFIG_JSON}")" - ARTIFACT_UPLOAD_PRE_COMMAND="$(jq -r '.artifact_upload_pre_command' <<< "${PROVIDER_CONFIG_JSON}")" - ARTIFACT_UPLOAD_URI_ROOT="$(jq -r '.artifact_upload_uri_root' <<< "${PROVIDER_CONFIG_JSON}")" - - { - echo "STORAGE_PROVIDER=${STORAGE_PROVIDER}" - echo "SCCACHE_PROFILE=${SCCACHE_PROFILE}" - echo "INTEGRATED_TESTS_ARTIFACT_BUCKET_PATH=${INTEGRATED_TESTS_ARTIFACT_BUCKET_PATH}" - echo "DOCKER_CA_BUNDLE_HOST_PATHS_JSON=${DOCKER_CA_BUNDLE_HOST_PATHS_JSON}" - echo "CMAKE_CUDA_ARCHITECTURES_JSON=${CMAKE_CUDA_ARCHITECTURES_JSON}" - echo "RUNNER_LABELS_JSON=${RUNNER_LABELS_JSON}" - echo "ARTIFACT_UPLOAD_COMMAND<<__EOF__" - printf '%s\n' "${ARTIFACT_UPLOAD_COMMAND}" - echo "__EOF__" - echo "ARTIFACT_UPLOAD_PRE_COMMAND<<__EOF__" - printf '%s\n' "${ARTIFACT_UPLOAD_PRE_COMMAND}" - echo "__EOF__" - echo "ARTIFACT_UPLOAD_URI_ROOT=${ARTIFACT_UPLOAD_URI_ROOT}" - echo "ARTIFACT_PUBLIC_URL_ROOT=${ARTIFACT_PUBLIC_URL_ROOT}" - echo "ARTIFACT_PUBLIC_URL_BUCKET_SCOPED=${ARTIFACT_PUBLIC_URL_BUCKET_SCOPED}" - } >> "$GITHUB_OUTPUT" - # PR must be assigned to be merged. # This job will fail if this is not the case. if_not_unassigned_pull_request: @@ -337,7 +133,7 @@ jobs: # Those are quite fast and can efficiently benefit from the `sccache' tool to make them even faster. cpu_builds: name: ${{ matrix.name }} - needs: [is_not_draft_pull_request, resolve_ci_provider] + needs: [is_not_draft_pull_request] strategy: # In-progress jobs will not be cancelled if there is a failure fail-fast : false @@ -352,9 +148,9 @@ jobs: # ENABLE_HYPRE: ON # ENABLE_TRILINOS: OFF # GEOS_ENABLE_BOUNDS_CHECK: ON - # RUNNER_KEY: cpu_heavy + # RUNS_ON: streak2 # NPROC: 8 - # DOCKER_RUN_ARGS: "--cpus=8 --memory=192g" + # DOCKER_RUN_ARGS: "--cpus=8 --memory=192g -v /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro -v /etc/pki/tls/certs/ca-bundle.crt:/certs/ca-bundle.crt:ro" # HOST_CONFIG: /spack-generated.cmake - name: Ubuntu 24.04 - gcc 13 debug @@ -365,10 +161,9 @@ jobs: ENABLE_HYPRE: ON ENABLE_TRILINOS: OFF GEOS_ENABLE_BOUNDS_CHECK: ON - # Resolved from .github/ci/orgs/.json. - RUNNER_KEY: cpu_heavy + RUNS_ON: streak2 NPROC: 4 - DOCKER_RUN_ARGS: "--cpus=8 --memory=192g" + DOCKER_RUN_ARGS: "--cpus=8 --memory=192g -v /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro -v /etc/pki/tls/certs/ca-bundle.crt:/certs/ca-bundle.crt:ro" HOST_CONFIG: /spack-generated.cmake - name: Ubuntu 24.04 - gcc 13 @@ -451,12 +246,10 @@ jobs: ENABLE_HYPRE: ${{ matrix.ENABLE_HYPRE }} ENABLE_TRILINOS: ${{ matrix.ENABLE_TRILINOS }} GEOS_ENABLE_BOUNDS_CHECK: ${{ matrix.GEOS_ENABLE_BOUNDS_CHECK }} - STORAGE_PROVIDER: ${{ needs.resolve_ci_provider.outputs.STORAGE_PROVIDER }} - SCCACHE_PROFILE: ${{ needs.resolve_ci_provider.outputs.SCCACHE_PROFILE }} + GCP_BUCKET: ${{ matrix.GCP_BUCKET }} HOST_CONFIG: ${{ matrix.HOST_CONFIG }} NPROC: ${{ matrix.NPROC || '' }} - DOCKER_CA_BUNDLE_HOST_PATH: ${{ fromJSON(needs.resolve_ci_provider.outputs.DOCKER_CA_BUNDLE_HOST_PATHS_JSON || '{}')[matrix.RUNNER_KEY || 'default'] || '' }} - RUNS_ON: ${{ fromJSON(needs.resolve_ci_provider.outputs.RUNNER_LABELS_JSON)[matrix.RUNNER_KEY || 'default'] }} + RUNS_ON: ${{ matrix.RUNS_ON || 'ubuntu-22.04' }} secrets: inherit # If the 'ci: run integrated tests' PR label is found, the integrated tests will be run immediately after the cpu jobs. @@ -464,7 +257,6 @@ jobs: run_integrated_tests: needs: - is_not_draft_pull_request - - resolve_ci_provider - cpu_builds uses: ./.github/workflows/build_and_test.yml secrets: inherit @@ -477,18 +269,10 @@ jobs: ENABLE_HYPRE: ON ENABLE_TRILINOS: OFF GEOS_ENABLE_BOUNDS_CHECK: ON - STORAGE_PROVIDER: ${{ needs.resolve_ci_provider.outputs.STORAGE_PROVIDER }} - SCCACHE_PROFILE: ${{ needs.resolve_ci_provider.outputs.SCCACHE_PROFILE }} - ARTIFACT_UPLOAD_BUCKET_PATH: ${{ needs.resolve_ci_provider.outputs.INTEGRATED_TESTS_ARTIFACT_BUCKET_PATH }} - ARTIFACT_UPLOAD_COMMAND: ${{ needs.resolve_ci_provider.outputs.ARTIFACT_UPLOAD_COMMAND }} - ARTIFACT_UPLOAD_PRE_COMMAND: ${{ needs.resolve_ci_provider.outputs.ARTIFACT_UPLOAD_PRE_COMMAND }} - ARTIFACT_UPLOAD_URI_ROOT: ${{ needs.resolve_ci_provider.outputs.ARTIFACT_UPLOAD_URI_ROOT }} - ARTIFACT_PUBLIC_URL_ROOT: ${{ needs.resolve_ci_provider.outputs.ARTIFACT_PUBLIC_URL_ROOT }} - ARTIFACT_PUBLIC_URL_BUCKET_SCOPED: ${{ needs.resolve_ci_provider.outputs.ARTIFACT_PUBLIC_URL_BUCKET_SCOPED }} - DOCKER_CA_BUNDLE_HOST_PATH: ${{ fromJSON(needs.resolve_ci_provider.outputs.DOCKER_CA_BUNDLE_HOST_PATHS_JSON || '{}').integrated_tests || '' }} - RUNS_ON: ${{ fromJSON(needs.resolve_ci_provider.outputs.RUNNER_LABELS_JSON).integrated_tests }} + GCP_BUCKET: geosx/integratedTests + RUNS_ON: streak2-32core NPROC: 32 - DOCKER_RUN_ARGS: "--cpus=32 --memory=256g" + DOCKER_RUN_ARGS: "--cpus=32 --memory=256g -v /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro -v /etc/pki/tls/certs/ca-bundle.crt:/certs/ca-bundle.crt:ro" REQUIRED_LABEL: "ci: run integrated tests" LOCAL_BASELINE_DIR: /data/GEOS/baselines HOST_CONFIG: /spack-generated.cmake @@ -511,9 +295,10 @@ jobs: # code_coverage: # needs: # - is_not_draft_pull_request - # - resolve_ci_provider # uses: ./.github/workflows/build_and_test.yml - # secrets: inherit + # secrets: + # CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + # GOOGLE_CLOUD_GCP: ${{ secrets.GOOGLE_CLOUD_GCP }} # with: # BUILD_AND_TEST_CLI_ARGS: "--no-run-unit-tests" # CMAKE_BUILD_TYPE: Debug @@ -522,13 +307,11 @@ jobs: # DOCKER_REPOSITORY: geosx/ubuntu24.04-gcc13 # ENABLE_HYPRE: ON # ENABLE_TRILINOS: OFF - # SCCACHE_PROFILE: ${{ needs.resolve_ci_provider.outputs.SCCACHE_PROFILE }} - # RUNS_ON: ${{ fromJSON(needs.resolve_ci_provider.outputs.RUNNER_LABELS_JSON).code_coverage }} - # DOCKER_CA_BUNDLE_HOST_PATH: ${{ fromJSON(needs.resolve_ci_provider.outputs.DOCKER_CA_BUNDLE_HOST_PATHS_JSON || '{}').code_coverage || '' }} + # RUNS_ON: streak2 # REQUIRED_LABEL: "ci: run code coverage" # HOST_CONFIG: /spack-generated.cmake # NPROC: 4 - # DOCKER_RUN_ARGS: "--cpus=8 --memory=256g" + # DOCKER_RUN_ARGS: "--cpus=8 --memory=256g -v /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro -v /etc/pki/tls/certs/ca-bundle.crt:/certs/ca-bundle.crt:ro" # mac_builds: @@ -547,7 +330,6 @@ jobs: name: ${{ matrix.name }} needs: - is_not_draft_pull_request - - resolve_ci_provider strategy: # In-progress jobs will not be cancelled if there is a failure fail-fast : false @@ -562,10 +344,9 @@ jobs: ENABLE_HYPRE: ON ENABLE_TRILINOS: OFF GEOS_ENABLE_BOUNDS_CHECK: OFF - # Resolved from .github/ci/orgs/.json. - RUNNER_KEY: cuda + RUNS_ON: streak2 NPROC: 8 - DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia" + DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia -v /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro -v /etc/pki/tls/certs/ca-bundle.crt:/certs/ca-bundle.crt:ro" HOST_CONFIG: /spack-generated.cmake - name: Ubuntu 24.04 - gcc 13 + CUDA 12.9.1 @@ -577,9 +358,9 @@ jobs: ENABLE_HYPRE: ON ENABLE_TRILINOS: OFF GEOS_ENABLE_BOUNDS_CHECK: OFF - RUNNER_KEY: cuda + RUNS_ON: streak2 NPROC: 8 - DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia" + DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia -v /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro -v /etc/pki/tls/certs/ca-bundle.crt:/certs/ca-bundle.crt:ro" HOST_CONFIG: /spack-generated.cmake - name: Ubuntu 24.04 - clang 19 + CUDA 12.9.1 @@ -591,9 +372,9 @@ jobs: ENABLE_HYPRE: ON ENABLE_TRILINOS: OFF GEOS_ENABLE_BOUNDS_CHECK: OFF - RUNNER_KEY: cuda + RUNS_ON: streak2 NPROC: 8 - DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia" + DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia -v /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro -v /etc/pki/tls/certs/ca-bundle.crt:/certs/ca-bundle.crt:ro" HOST_CONFIG: /spack-generated.cmake # - name: Rocky Linux 8 - clang 19 + CUDA 12.9.1 @@ -605,9 +386,9 @@ jobs: # ENABLE_TRILINOS: OFF # GEOS_ENABLE_BOUNDS_CHECK: OFF # DOCKER_REPOSITORY: geosx/rockylinux8-clang19-cuda12.9.1 - # RUNNER_KEY: cuda + # RUNS_ON: streak2 # NPROC: 8 - # DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all" + # DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all -v /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro -v /etc/pki/tls/certs/ca-bundle.crt:/certs/ca-bundle.crt:ro" # HOST_CONFIG: /spack-generated.cmake - name: Rocky Linux 8 - gcc 13 + CUDA 12.9.1 @@ -619,9 +400,9 @@ jobs: ENABLE_TRILINOS: OFF GEOS_ENABLE_BOUNDS_CHECK: OFF DOCKER_REPOSITORY: geosx/rockylinux8-gcc13-cuda12.9.1 - RUNNER_KEY: cuda + RUNS_ON: streak2 NPROC: 8 - DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia" + DOCKER_RUN_ARGS: "--cpus=8 --memory=128g --runtime=nvidia -v /etc/pki/tls/certs/ca-bundle.crt:/etc/pki/tls/certs/ca-bundle.crt:ro -v /etc/pki/tls/certs/ca-bundle.crt:/certs/ca-bundle.crt:ro" HOST_CONFIG: /spack-generated.cmake # Below this line, jobs that deploy to Google Cloud. @@ -630,7 +411,7 @@ jobs: with: BUILD_AND_TEST_CLI_ARGS: ${{ matrix.BUILD_AND_TEST_CLI_ARGS }} CMAKE_BUILD_TYPE: ${{ matrix.CMAKE_BUILD_TYPE }} - CMAKE_CUDA_ARCHITECTURES: ${{ fromJSON(needs.resolve_ci_provider.outputs.CMAKE_CUDA_ARCHITECTURES_JSON)[matrix.RUNNER_KEY || 'default'] }} + CMAKE_CUDA_ARCHITECTURES: "86" BUILD_GENERATOR: ${{ matrix.BUILD_GENERATOR }} DOCKER_IMAGE_TAG: ${{ needs.is_not_draft_pull_request.outputs.DOCKER_IMAGE_TAG }} DOCKER_REPOSITORY: ${{ matrix.DOCKER_REPOSITORY }} @@ -639,11 +420,9 @@ jobs: ENABLE_HYPRE: ${{ matrix.ENABLE_HYPRE }} ENABLE_TRILINOS: ${{ matrix.ENABLE_TRILINOS }} GEOS_ENABLE_BOUNDS_CHECK: ${{ matrix.GEOS_ENABLE_BOUNDS_CHECK }} - SCCACHE_PROFILE: ${{ needs.resolve_ci_provider.outputs.SCCACHE_PROFILE }} HOST_CONFIG: ${{ matrix.HOST_CONFIG }} NPROC: ${{ matrix.NPROC }} - DOCKER_CA_BUNDLE_HOST_PATH: ${{ fromJSON(needs.resolve_ci_provider.outputs.DOCKER_CA_BUNDLE_HOST_PATHS_JSON || '{}')[matrix.RUNNER_KEY || 'default'] || '' }} - RUNS_ON: ${{ fromJSON(needs.resolve_ci_provider.outputs.RUNNER_LABELS_JSON)[matrix.RUNNER_KEY || 'default'] }} + RUNS_ON: ${{ matrix.RUNS_ON }} REQUIRED_LABEL: "ci: run CUDA builds" secrets: inherit diff --git a/scripts/ci_build_and_test_in_container.sh b/scripts/ci_build_and_test_in_container.sh index 81193ce3b4d..eedab9352d3 100755 --- a/scripts/ci_build_and_test_in_container.sh +++ b/scripts/ci_build_and_test_in_container.sh @@ -20,85 +20,11 @@ function or_die () { local status=$? if [[ $status != 0 ]] ; then - if [[ -n "${CURRENT_PHASE_LABEL:-}" ]]; then - phase_finish "${status}" - fi echo ERROR $status command: $@ exit $status fi } -PHASE_TIMINGS=() -CURRENT_PHASE_LABEL="" -CURRENT_PHASE_START="" -tempdir="" - -function now_epoch () { - date +%s -} - -function format_duration () { - local total_seconds=$1 - local hours=$(( total_seconds / 3600 )) - local minutes=$(( (total_seconds % 3600) / 60 )) - local seconds=$(( total_seconds % 60 )) - - if (( hours > 0 )); then - printf '%dh %02dm %02ds' "${hours}" "${minutes}" "${seconds}" - elif (( minutes > 0 )); then - printf '%dm %02ds' "${minutes}" "${seconds}" - else - printf '%ds' "${seconds}" - fi -} - -function phase_start () { - CURRENT_PHASE_LABEL="$1" - CURRENT_PHASE_START="$(now_epoch)" - echo ">>> ${CURRENT_PHASE_LABEL} started at $(date -u +"%Y-%m-%dT%H:%M:%SZ")" -} - -function phase_finish () { - local status="${1:-0}" - local label="${CURRENT_PHASE_LABEL:-}" - local start="${CURRENT_PHASE_START:-}" - - if [[ -z "${label}" || -z "${start}" ]]; then - return 0 - fi - - local duration=$(( $(now_epoch) - start )) - PHASE_TIMINGS+=("${label}|${duration}|${status}") - - if [[ "${status}" -eq 0 ]]; then - echo ">>> ${label} completed in $(format_duration "${duration}")" - else - echo ">>> ${label} failed after $(format_duration "${duration}") (exit ${status})" - fi - - CURRENT_PHASE_LABEL="" - CURRENT_PHASE_START="" -} - -function print_phase_summary () { - local entry label duration status status_text - - if [[ ${#PHASE_TIMINGS[@]} -eq 0 ]]; then - return 0 - fi - - echo "Phase timing summary:" - for entry in "${PHASE_TIMINGS[@]}"; do - IFS='|' read -r label duration status <<< "${entry}" - if [[ "${status}" -eq 0 ]]; then - status_text="ok" - else - status_text="exit ${status}" - fi - printf ' - %s: %s (%s)\n' "${label}" "$(format_duration "${duration}")" "${status_text}" - done -} - function usage () { >&2 cat << EOF Usage: $0 @@ -144,10 +70,8 @@ Usage: $0 Internal mountpoint where the geos repository will be available. --run-integrated-tests Run the integrated tests. Then bundle and send the results to the cloud. - --use-sccache - Enable sccache as compiler launcher. - --sccache-config config.toml - Relative path to an sccache config file to use inside the container. + --sccache-credentials credentials.json + Basename of the json credentials file to connect to the sccache cloud cache. --test-code-style --test-documentation -h | --help @@ -159,7 +83,7 @@ exit 1 # Then we'll move to the build dir. or_die cd $(dirname $0)/.. -args=$(or_die getopt -a -o h --long build-exe-only,cmake-build-type:,cmake-cuda-architectures:,code-coverage,ctest-parallel-level:,data-basename:,geos-enable-bounds-check:,enable-hypre:,enable-hypre-device:,enable-trilinos:,exchange-dir:,host-config:,install-dir-basename:,makefile,ninja,no-install-schema,no-run-unit-tests,nproc:,repository:,run-integrated-tests,sccache-config:,test-code-style,test-documentation,use-native-architecture,use-sccache,help -- "$@") +args=$(or_die getopt -a -o h --long build-exe-only,cmake-build-type:,cmake-cuda-architectures:,code-coverage,ctest-parallel-level:,data-basename:,geos-enable-bounds-check:,enable-hypre:,enable-hypre-device:,enable-trilinos:,exchange-dir:,host-config:,install-dir-basename:,makefile,ninja,no-install-schema,no-run-unit-tests,nproc:,repository:,run-integrated-tests,sccache-credentials:,test-code-style,test-documentation,use-native-architecture,help -- "$@") # Variables with default values BUILD_EXE_ONLY=false @@ -179,8 +103,6 @@ CODE_COVERAGE=false CTEST_PARALLEL_LEVEL_ARG="" NPROC="$(nproc)" GEOS_ENABLE_BOUNDS_CHECK=ON -SCCACHE_BIN="" -USE_SCCACHE=false CMAKE_CUDA_ARCHITECTURES_ARGS=() CMAKE_NATIVE_ARCHITECTURE_ARGS=() ATS_CMAKE_ARGS=() @@ -233,8 +155,7 @@ do --ctest-parallel-level) CTEST_PARALLEL_LEVEL_ARG=$2 shift 2;; - --sccache-config) SCCACHE_CONFIG_FILE=$2; shift 2;; - --use-sccache) USE_SCCACHE=true; shift;; + --sccache-credentials) SCCACHE_CREDS=$2; shift 2;; --test-code-style) TEST_CODE_STYLE=true; shift;; --test-documentation) TEST_DOCUMENTATION=true; shift;; -h | --help) usage; shift;; @@ -252,15 +173,7 @@ fi cleanup() { - if [[ -n "${CURRENT_PHASE_LABEL:-}" ]]; then - phase_finish 1 - fi - - print_phase_summary echo "Container cleanup..." - if [[ -n "${tempdir:-}" ]]; then - rm -rf "${tempdir}" || true - fi rm -rf "${GEOS_SRC_DIR}/src/docs/sphinx/datastructure" || true if [[ -n "${HOST_UID:-}" && -n "${HOST_GID:-}" ]]; then @@ -282,35 +195,33 @@ else GEOS_LA_INTERFACE=Trilinos fi -if [[ "${USE_SCCACHE}" == true ]]; then - SCCACHE_BIN=${SCCACHE:-$(command -v sccache || true)} - - if [[ -z "${SCCACHE_BIN}" ]]; then - echo "sccache was requested, but no sccache binary is available in the container." - exit 1 - fi - - if [[ -n "${SCCACHE_CONFIG_FILE:-}" ]]; then - if [[ ! -f "${GEOS_SRC_DIR}/${SCCACHE_CONFIG_FILE}" ]]; then - echo "Unable to find requested sccache config file at ${GEOS_SRC_DIR}/${SCCACHE_CONFIG_FILE}." - exit 1 - fi - - or_die mkdir -p ${HOME}/.config/sccache - or_die cp "${GEOS_SRC_DIR}/${SCCACHE_CONFIG_FILE}" "${HOME}/.config/sccache/config" - fi - - # Backend-specific credentials and endpoints are injected through the environment and/or config file. - SCCACHE_CMAKE_ARGS="-DCMAKE_C_COMPILER_LAUNCHER=${SCCACHE_BIN} -DCMAKE_CXX_COMPILER_LAUNCHER=${SCCACHE_BIN} -DCMAKE_CUDA_COMPILER_LAUNCHER=${SCCACHE_BIN}" - - if [[ -f /certs/ca-bundle.crt ]]; then - export SSL_CERT_FILE=/certs/ca-bundle.crt - export CURL_CA_BUNDLE=/certs/ca-bundle.crt - export REQUESTS_CA_BUNDLE=/certs/ca-bundle.crt - fi +if [[ ! -z "${SCCACHE_CREDS}" ]]; then + # The credential json file is available at the root of the geos repository. + # We hereafter create the config file that points to it. + # We use this file since it's managed by the 'google-github-actions/auth' actions. + or_die mkdir -p ${HOME}/.config/sccache + or_die cat <> ${HOME}/.config/sccache/config +[cache.gcs] +rw_mode = "READ_WRITE" +cred_path = "${GEOS_SRC_DIR}/${SCCACHE_CREDS}" +bucket = "geos-dev" +key_prefix = "sccache" +EOT + + # To use `sccache`, it's enough to tell `cmake` to launch the compilation using `sccache`. + # The path to the `sccache` executable is available through the SCCACHE environment variable. + SCCACHE_CMAKE_ARGS="-DCMAKE_CXX_COMPILER_LAUNCHER=${SCCACHE} -DCMAKE_CUDA_COMPILER_LAUNCHER=${SCCACHE}" + + case "$(hostname -f 2>/dev/null || hostname)" in + *.llnl.gov|streak2*|streak*) + export SSL_CERT_FILE=/certs/ca-bundle.crt + export CURL_CA_BUNDLE=/certs/ca-bundle.crt + export REQUESTS_CA_BUNDLE=/certs/ca-bundle.crt + ;; + esac echo "sccache initial state" - ${SCCACHE_BIN} --show-stats || true + ${SCCACHE} --show-stats fi if [ -z "${NPROC}" ]; then @@ -325,7 +236,6 @@ if [[ -n "${CTEST_PARALLEL_LEVEL_ARG}" ]]; then fi if [[ "${RUN_INTEGRATED_TESTS}" = true ]]; then - phase_start "Set up integrated test environment" echo "Running the integrated tests has been requested." # We install the python environment required by ATS to run the integrated tests. or_die apt-get update @@ -339,6 +249,7 @@ if [[ "${RUN_INTEGRATED_TESTS}" = true ]]; then # Setup a temporary directory to hold tests tempdir=$(mktemp -d) echo "Setting up a temporary directory to hold tests and baselines: $tempdir" + trap "rm -rf $tempdir" EXIT ATS_BASELINE_DIR=$tempdir/GEOS_integratedTests_baselines ATS_WORKING_DIR=$tempdir/GEOS_integratedTests_working @@ -349,7 +260,6 @@ if [[ "${RUN_INTEGRATED_TESTS}" = true ]]; then "-DPython3_EXECUTABLE=${ATS_PYTHON_HOME}/bin/python3" "-DATS_BASELINE_DIR=${ATS_BASELINE_DIR}" "-DATS_WORKING_DIR=${ATS_WORKING_DIR}") - phase_finish 0 fi @@ -402,7 +312,6 @@ fi # This will tells OpenMPI to discover the number of hardware threads on the node, # and use that as the number of slots available. (There is a distinction between threads and cores). GEOS_BUILD_DIR=/tmp/geos-build -phase_start "Configure" or_die python3 scripts/config-build.py \ -hc ${HOST_CONFIG} \ -bt ${CMAKE_BUILD_TYPE} \ @@ -422,29 +331,23 @@ or_die python3 scripts/config-build.py \ ${SCCACHE_CMAKE_ARGS} \ ${LCOV_CMAKE_ARGS} \ "${ATS_CMAKE_ARGS[@]}" -phase_finish 0 # The configuration step is now over, we can now move to the build directory for the build! or_die cd ${GEOS_BUILD_DIR} # Code style check if [[ "${TEST_CODE_STYLE}" = true ]]; then - phase_start "Code style check" or_die ctest --output-on-failure -R "testUncrustifyCheck" - phase_finish 0 exit 0 fi # Documentation check if [[ "${TEST_DOCUMENTATION}" = true ]]; then - phase_start "Documentation check" or_die ctest --output-on-failure -R "testDoxygenCheck" - phase_finish 0 exit 0 fi # Performing the requested build. -phase_start "Build" if [[ "${BUILD_EXE_ONLY}" = true ]]; then or_die cmake --build . -j $NPROC --target geosx else @@ -463,30 +366,25 @@ else or_die tar czf ${DATA_EXCHANGE_DIR}/${DATA_BASENAME_WE}.tar.gz --directory=${GEOS_TPL_DIR}/.. --transform "s|^./|${DATA_BASENAME_WE}/|" . fi fi -phase_finish 0 -if [[ -n "${SCCACHE_BIN}" ]]; then +if [[ ! -z "${SCCACHE_CREDS}" ]]; then echo "sccache post-build state" - or_die ${SCCACHE_BIN} --show-adv-stats + or_die ${SCCACHE} --show-adv-stats fi if [[ "${CODE_COVERAGE}" = true ]]; then - phase_start "Generate code coverage" export OMP_NUM_THREADS=1 or_die cmake --build . --target coreComponents_coverage - or_die cp -r ${GEOS_BUILD_DIR}/coreComponents_coverage.info.cleaned ${GEOS_SRC_DIR}/geos_coverage.info.cleaned - phase_finish 0 + cp -r ${GEOS_BUILD_DIR}/coreComponents_coverage.info.cleaned ${GEOS_SRC_DIR}/geos_coverage.info.cleaned fi # Run the unit tests (excluding previously ran checks). if [[ "${RUN_UNIT_TESTS}" = true ]]; then - phase_start "Unit tests" if [ ${HOSTNAME} == 'streak.llnl.gov' ] || [ ${HOSTNAME} == 'streak2.llnl.gov' ]; then or_die ctest --output-on-failure -E "testUncrustifyCheck|testDoxygenCheck|testExternalSolvers" else or_die ctest --output-on-failure -E "testUncrustifyCheck|testDoxygenCheck" fi - phase_finish 0 fi if [[ "${RUN_INTEGRATED_TESTS}" = true ]]; then @@ -499,9 +397,7 @@ if [[ "${RUN_INTEGRATED_TESTS}" = true ]]; then fi # We split the process in two steps. First installing the environment, then running the tests. - phase_start "Build ATS environment" or_die cmake --build . --target ats_environment - phase_finish 0 # The tests are not run using cmake (`cmake --build . --verbose --target ats_run`) # because with ninja it swallows the output while all the @@ -511,27 +407,15 @@ if [[ "${RUN_INTEGRATED_TESTS}" = true ]]; then ls -lR /tmp/geos/baselines echo "Running integrated tests..." - phase_start "Integrated tests" integratedTests/geos_ats.sh --baselineCacheDirectory /tmp/geos/baselines - ATS_RUN_STATUS=$? - phase_finish "${ATS_RUN_STATUS}" - - phase_start "Process integrated test logs" - PROCESS_LOGS_STATUS=0 echo "Processing logs..." - bin/geos_ats_process_tests_fails --directory integratedTests/TestResults &> integratedTests/TestResults/processedTestsLogs.txt || PROCESS_LOGS_STATUS=$? - if [[ "${PROCESS_LOGS_STATUS}" -eq 0 ]]; then - echo "Packing logs..." - tar -czf ${DATA_EXCHANGE_DIR}/test_logs_${DATA_BASENAME_WE}.tar.gz integratedTests/TestResults || PROCESS_LOGS_STATUS=$? - fi - phase_finish "${PROCESS_LOGS_STATUS}" + bin/geos_ats_process_tests_fails --directory integratedTests/TestResults &> integratedTests/TestResults/processedTestsLogs.txt + echo "Packing logs..." + tar -czf ${DATA_EXCHANGE_DIR}/test_logs_${DATA_BASENAME_WE}.tar.gz integratedTests/TestResults echo "Checking results..." - phase_start "Check integrated test results" bin/geos_ats_log_check integratedTests/TestResults/test_results.ini -y ${GEOS_SRC_DIR}/.integrated_tests.yaml &> $tempdir/log_check.txt - LOG_CHECK_STATUS=$? cat $tempdir/log_check.txt - phase_finish "${LOG_CHECK_STATUS}" if grep -q "Overall status: PASSED" "$tempdir/log_check.txt"; then echo "IntegratedTests passed. No rebaseline required." @@ -541,15 +425,10 @@ if [[ "${RUN_INTEGRATED_TESTS}" = true ]]; then # Rebaseline and pack into an archive echo "Rebaselining..." - phase_start "Rebaseline integrated tests" - REBASELINE_STATUS=0 - integratedTests/geos_ats.sh -a rebaselinefailed || REBASELINE_STATUS=$? + integratedTests/geos_ats.sh -a rebaselinefailed - if [[ "${REBASELINE_STATUS}" -eq 0 ]]; then - echo "Packing baselines..." - integratedTests/geos_ats.sh -a pack_baselines --baselineArchiveName ${DATA_EXCHANGE_DIR}/baseline_${DATA_BASENAME_WE}.tar.gz --baselineCacheDirectory /tmp/geos/baselines || REBASELINE_STATUS=$? - fi - phase_finish "${REBASELINE_STATUS}" + echo "Packing baselines..." + integratedTests/geos_ats.sh -a pack_baselines --baselineArchiveName ${DATA_EXCHANGE_DIR}/baseline_${DATA_BASENAME_WE}.tar.gz --baselineCacheDirectory /tmp/geos/baselines INTEGRATED_TEST_EXIT_STATUS=1 fi @@ -560,15 +439,11 @@ if [[ "${RUN_INTEGRATED_TESTS}" = true ]]; then fi # Cleaning the build directory. -phase_start "Clean build directory" or_die cmake --build . --target clean -phase_finish 0 # Clean the repository -phase_start "Clean repository" or_die cd ${GEOS_SRC_DIR}/inputFiles -find . -name '*.pyc' -delete -phase_finish 0 +find . -name *.pyc | xargs rm -f # If we're here, either everything went OK or we have to deal with the integrated tests manually. if [[ ! -z "${INTEGRATED_TEST_EXIT_STATUS+x}" ]]; then