|
| 1 | +name: 'LATdx Apex Tests' |
| 2 | +description: >- |
| 3 | + Install the LATdx CLI, resolve a license (explicit key via the |
| 4 | + LATDX_LICENSE_KEY env var, or a short-lived OSS license minted from the |
| 5 | + GitHub Actions OIDC token on public repos), and run the full local Apex |
| 6 | + test suite against the job's default Salesforce org. |
| 7 | +
|
| 8 | +inputs: |
| 9 | + cli-version: |
| 10 | + description: "LATdx CLI version to install (semver like '0.31.1') or 'latest'." |
| 11 | + required: false |
| 12 | + default: 'latest' |
| 13 | + |
| 14 | +runs: |
| 15 | + using: composite |
| 16 | + steps: |
| 17 | + # LATdx's cache Phase 4 runs an apex-ls bridge on the JVM. Hosted images |
| 18 | + # vary (ubuntu-latest ships a recent Temurin, ubuntu-22.04 a default JDK |
| 19 | + # too old for the bridge jar -> "JVM exited (code=1)"), so pin a known-good |
| 20 | + # JDK on PATH rather than relying on the image default. |
| 21 | + - name: 'Set up Java for LATdx apex-ls' |
| 22 | + uses: actions/setup-java@v4 |
| 23 | + with: |
| 24 | + distribution: temurin |
| 25 | + java-version: '17' |
| 26 | + |
| 27 | + - name: 'Install LATdx CLI' |
| 28 | + shell: bash |
| 29 | + env: |
| 30 | + CLI_VERSION: ${{ inputs.cli-version }} |
| 31 | + run: | |
| 32 | + set -euo pipefail |
| 33 | + if [[ ! "$CLI_VERSION" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+)$ ]]; then |
| 34 | + echo "::error::Invalid 'cli-version' input. Must be 'latest' or a semver like '0.31.1'." |
| 35 | + exit 1 |
| 36 | + fi |
| 37 | + # latdx.com serves the maintained install script, but Cloudflare |
| 38 | + # returns 403 to some hosted-runner egress IP ranges; fall back to |
| 39 | + # the GitHub raw mirror so the install succeeds from any runner. |
| 40 | + script="" |
| 41 | + for url in "https://latdx.com/install.sh" "https://raw.githubusercontent.com/nebulity/latdx-cli/main/install.sh"; do |
| 42 | + if script="$(curl -fsSL "$url")"; then |
| 43 | + break |
| 44 | + fi |
| 45 | + script="" |
| 46 | + done |
| 47 | + if [ -z "$script" ]; then |
| 48 | + echo "::error::Could not download the LATdx install script from any source." |
| 49 | + exit 1 |
| 50 | + fi |
| 51 | + if [ "$CLI_VERSION" = "latest" ]; then |
| 52 | + printf '%s' "$script" | bash |
| 53 | + else |
| 54 | + printf '%s' "$script" | bash -s -- "$CLI_VERSION" |
| 55 | + fi |
| 56 | + echo "$HOME/.local/bin" >> "$GITHUB_PATH" |
| 57 | +
|
| 58 | + - name: 'Verify LATdx CLI' |
| 59 | + shell: bash |
| 60 | + run: latdx --version |
| 61 | + |
| 62 | + - name: 'Resolve LATdx license' |
| 63 | + shell: bash |
| 64 | + run: | |
| 65 | + # The runner injects -e -o pipefail; this step must never fail the |
| 66 | + # job: every problem degrades to the free-tier cap with a warning. |
| 67 | + set +e +o pipefail |
| 68 | +
|
| 69 | + # Precedence: |
| 70 | + # 1. LATDX_LICENSE_KEY already in the environment (repo secret) -> use it. |
| 71 | + # 2. GH OIDC token available + repo public -> exchange for an OSS |
| 72 | + # auto-license via https://latdx.com/api/oss/license. |
| 73 | + # 3. Nothing -> daemon runs free-tier (capped at 100 tests, exit 2). |
| 74 | +
|
| 75 | + if [ -n "${LATDX_LICENSE_KEY:-}" ]; then |
| 76 | + echo "Using LATdx license from environment." |
| 77 | + exit 0 |
| 78 | + fi |
| 79 | +
|
| 80 | + if [ -z "${ACTIONS_ID_TOKEN_REQUEST_TOKEN:-}" ] || [ -z "${ACTIONS_ID_TOKEN_REQUEST_URL:-}" ]; then |
| 81 | + echo "::warning title=LATdx OSS license::OIDC token unavailable (missing 'permissions: id-token: write' on the job). Free-tier cap (100 tests/run) applies." |
| 82 | + exit 0 |
| 83 | + fi |
| 84 | +
|
| 85 | + OIDC_RESPONSE="$(curl -sS -f -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \ |
| 86 | + "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=https%3A%2F%2Flatdx.com" 2>/dev/null)" |
| 87 | + CURL_RC=$? |
| 88 | + if [ "$CURL_RC" -ne 0 ]; then |
| 89 | + echo "::warning title=LATdx OSS license::OIDC token mint failed (curl rc=${CURL_RC}); falling back to free-tier cap." |
| 90 | + exit 0 |
| 91 | + fi |
| 92 | + OIDC_TOKEN="$(printf '%s' "$OIDC_RESPONSE" | jq -r '.value // empty' 2>/dev/null)" |
| 93 | + if [ -z "$OIDC_TOKEN" ]; then |
| 94 | + echo "::warning title=LATdx OSS license::OIDC response not parseable (length ${#OIDC_RESPONSE}); falling back to free-tier cap." |
| 95 | + exit 0 |
| 96 | + fi |
| 97 | + echo "Minted GitHub OIDC token (length ${#OIDC_TOKEN})." |
| 98 | +
|
| 99 | + EXCHANGE_BODY="$(mktemp)" |
| 100 | + EXCHANGE_HEADERS="$(mktemp)" |
| 101 | + trap 'rm -f "$EXCHANGE_BODY" "$EXCHANGE_HEADERS"' EXIT |
| 102 | + HTTP_CODE="$(curl -sS -o "$EXCHANGE_BODY" -D "$EXCHANGE_HEADERS" -w "%{http_code}" \ |
| 103 | + -X POST https://latdx.com/api/oss/license \ |
| 104 | + -H "Authorization: Bearer $OIDC_TOKEN" \ |
| 105 | + -H "Content-Type: application/json" \ |
| 106 | + --max-time 15)" |
| 107 | + if [ $? -ne 0 ]; then |
| 108 | + HTTP_CODE="000" |
| 109 | + fi |
| 110 | + echo "OSS license exchange returned HTTP ${HTTP_CODE}." |
| 111 | + # On any non-200, surface whether the response is the LATdx route's |
| 112 | + # JSON or an edge (Cloudflare) interstitial. The denied-request body |
| 113 | + # carries no secrets. `server`/`cf-ray` headers identify the edge. |
| 114 | + if [ "$HTTP_CODE" != "200" ]; then |
| 115 | + echo "--- response server header: $(grep -i '^server:' "$EXCHANGE_HEADERS" | tr -d '\r')" |
| 116 | + echo "--- cf-ray header: $(grep -i '^cf-ray:' "$EXCHANGE_HEADERS" | tr -d '\r')" |
| 117 | + echo "--- content-type: $(grep -i '^content-type:' "$EXCHANGE_HEADERS" | tr -d '\r')" |
| 118 | + echo "--- body (first 300 chars): $(head -c 300 "$EXCHANGE_BODY" | tr '\n' ' ')" |
| 119 | + fi |
| 120 | +
|
| 121 | + case "$HTTP_CODE" in |
| 122 | + 200) |
| 123 | + LATDX_JWT="$(jq -r '.license // empty' < "$EXCHANGE_BODY" 2>/dev/null)" |
| 124 | + if [ -z "$LATDX_JWT" ]; then |
| 125 | + echo "::warning title=LATdx OSS license::Exchange returned 200 without a license; falling back to free-tier cap." |
| 126 | + exit 0 |
| 127 | + fi |
| 128 | + echo "::add-mask::$LATDX_JWT" |
| 129 | + echo "LATDX_LICENSE_KEY=$LATDX_JWT" >> "$GITHUB_ENV" |
| 130 | + USED="$(jq -r '.monthly_used // "?"' < "$EXCHANGE_BODY" 2>/dev/null)" |
| 131 | + CAP="$(jq -r '.monthly_cap // "?"' < "$EXCHANGE_BODY" 2>/dev/null)" |
| 132 | + echo "OSS auto-license active (monthly_used=$USED, monthly_cap=$CAP) - free-tier cap lifted for this run." |
| 133 | + ;; |
| 134 | + 403) |
| 135 | + REASON="$(jq -r '.reason // "denied"' < "$EXCHANGE_BODY" 2>/dev/null)" |
| 136 | + ERROR="$(jq -r '.error // "OSS license denied."' < "$EXCHANGE_BODY" 2>/dev/null)" |
| 137 | + echo "::warning title=LATdx OSS license::${ERROR} (reason=${REASON}). Free-tier cap (100 tests/run) applies." |
| 138 | + ;; |
| 139 | + 429) |
| 140 | + USED="$(jq -r '.monthly_used // "?"' < "$EXCHANGE_BODY" 2>/dev/null)" |
| 141 | + CAP="$(jq -r '.monthly_cap // "?"' < "$EXCHANGE_BODY" 2>/dev/null)" |
| 142 | + RESET="$(jq -r '.reset_at // "next UTC month"' < "$EXCHANGE_BODY" 2>/dev/null)" |
| 143 | + echo "::warning title=LATdx OSS license::Monthly cap reached (${USED}/${CAP}); resets ${RESET}. Free-tier cap applies for this run." |
| 144 | + ;; |
| 145 | + 503) |
| 146 | + echo "::warning title=LATdx OSS license::OSS path temporarily unavailable. Free-tier cap applies for this run." |
| 147 | + ;; |
| 148 | + 000) |
| 149 | + echo "::warning title=LATdx OSS license::Could not reach the LATdx site. Free-tier cap applies for this run." |
| 150 | + ;; |
| 151 | + *) |
| 152 | + ERROR="$(jq -r '.error // ""' < "$EXCHANGE_BODY" 2>/dev/null)" |
| 153 | + echo "::warning title=LATdx OSS license::Unexpected response ${HTTP_CODE} from /api/oss/license (${ERROR}). Free-tier cap applies." |
| 154 | + ;; |
| 155 | + esac |
| 156 | +
|
| 157 | + - name: 'Run Apex tests with LATdx' |
| 158 | + shell: bash |
| 159 | + run: | |
| 160 | + set +e |
| 161 | + latdx test run |
| 162 | + rc=$? |
| 163 | + set -e |
| 164 | + # Exit 2 is EXIT_LICENSE_REQUIRED: the free-tier cap (100 tests) was |
| 165 | + # hit. Treat it as a non-fatal, informational outcome so the pipeline |
| 166 | + # stays green on the tests that did run; lift the cap with an OSS |
| 167 | + # auto-license or LATDX_LICENSE_KEY to run the full suite. |
| 168 | + if [ "$rc" -eq 2 ]; then |
| 169 | + echo "::warning title=LATdx license cap::Run halted at the free-tier cap (100 tests). Provide a license to run the full suite." |
| 170 | + exit 0 |
| 171 | + fi |
| 172 | + exit "$rc" |
0 commit comments