Skip to content

KONFLUX-14156 add curl retry and timeouts to OTP server calls - #951

Merged
glevi-rh merged 1 commit into
mainfrom
otp-curl-retry
Jun 30, 2026
Merged

KONFLUX-14156 add curl retry and timeouts to OTP server calls#951
glevi-rh merged 1 commit into
mainfrom
otp-curl-retry

Conversation

@glevi-rh

@glevi-rh glevi-rh commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Add a shell retry loop to OTP /store-key curl calls to handle transient failures under high concurrency (1% failure rate at 200 concurrent RPM builds on stone-stg-rh01).

Resolves: KONFLUX-14156

Based on #946 — refined to use a shell retry loop instead of curl's --retry-all-errors for precise control over which errors trigger a retry.

Changes

  • New deploy/operator/otp-utils.sh — shared curl_otp_store_key() function with retry loop and empty-token validation
  • deploy/operator/kustomization.yaml — add otp-utils.sh to all three provisioning ConfigMaps
  • deploy/operator/provision-shared-host.sh — source otp-utils.sh, replace inline curl + empty-token check with curl_otp_store_key()
  • deploy/operator/provision-host-macos.sh — same
  • deploy/operator/provision-host-windows.sh — same

The retry loop retries only on transient curl exit codes:

  • 6: DNS resolution failure — the reported issue
  • 7: connection refused — pod not ready
  • 22: HTTP error via --fail (e.g. 503 during startup)
  • 28: timeout — with --connect-timeout 5, this is a connect-phase timeout
  • 35: TLS handshake failure — cert not available after pod restart
  • 56: receive failure — connection dropped mid-transfer

All other errors fail immediately without retry.

Testing

  • make fmt passes
  • make lint passes
  • make test passes (46/46 specs, 78.4% composite coverage)
  • shellcheck passes (zero warnings on otp-utils.sh)
  • kustomize build renders otp-utils.sh in all three provisioning ConfigMaps
  • Local function test confirms retry on DNS failure and stderr-only logging
  • CI checks pass (go-ci, mpc-test, test-e2e)

Coverage

Shell-only changes — no Go code modified, no coverage impact.

Notes

  • curl's --retry-connrefused only covers exit code 7, not DNS failures (exit code 6). --retry-all-errors retries more broadly than needed. A shell loop gives precise control.
  • otp-utils.sh is a sourced library — it inherits set -eu, pipefail, and the ERR trap from the parent script.

Closes #945

@qodo-app-for-konflux-ci

Copy link
Copy Markdown

PR Summary by Qodo

Add curl retries/timeouts for OTP /store-key provisioning calls
🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

Description

• Add curl connect/overall timeouts to OTP /store-key POST calls to reduce build flakiness.
• Enable curl retries (including DNS failures) to handle transient resolution issues under
 concurrency.
• Apply the same retry policy consistently across shared-host, macOS, and Windows provisioning
 scripts.
Diagram

graph TD
  A["provision-shared-host.sh"] --> B(["curl POST /store-key\n(retry+timeouts)"]) --> G{{"OTP server"}}
  C["provision-host-macos.sh"] --> D(["curl POST /store-key\n(retry+timeouts)"]) --> G
  E["provision-host-windows.sh"] --> F(["curl POST /store-key\n(retry+timeouts)"]) --> G

  subgraph Legend
    direction LR
    _file["Script file"] ~~~ _call(["HTTP call"]) ~~~ _ext{{"Service"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Centralize OTP curl flags (DRY)
  • ➕ Reduces risk of the three scripts drifting over time
  • ➕ Makes future tuning (timeouts/retries) a one-line change
  • ➖ Requires introducing a shared helper/source file or duplicating a function definition across scripts
  • ➖ Slightly larger change than necessary for a targeted reliability fix
2. Exponential backoff / jittered retries
  • ➕ Reduces thundering-herd behavior if many builds retry simultaneously
  • ➕ Often more resilient for transient DNS/network issues
  • ➖ More custom logic to maintain vs curl built-ins
  • ➖ Harder to reason about/standardize across environments

Recommendation: The current approach (curl built-in timeouts + --retry-all-errors) is the best minimal-risk fix for transient DNS failures and keeps behavior consistent across environments. Consider a follow-up to centralize the curl option set to avoid divergence, but it’s not required to resolve this incident.

Files changed (3) +3 / -3

Bug fix (3) +3 / -3
provision-host-macos.shHarden OTP /store-key curl call with timeouts and retries +1/-1

Harden OTP /store-key curl call with timeouts and retries

• Adds curl connection/overall timeouts and retry flags (including --retry-all-errors) to the OTP /store-key POST. This reduces provisioning failures caused by transient DNS resolution issues.

deploy/operator/provision-host-macos.sh

provision-host-windows.shAdd retry/timeout policy to OTP /store-key curl call +1/-1

Add retry/timeout policy to OTP /store-key curl call

• Updates the OTP /store-key curl invocation to include connect timeout, max time, and retries on all errors. Keeps Windows provisioning behavior aligned with the other platforms.

deploy/operator/provision-host-windows.sh

provision-shared-host.shApply curl retry/timeouts to OTP /store-key POST in shared host provisioning +1/-1

Apply curl retry/timeouts to OTP /store-key POST in shared host provisioning

• Adds curl retry and timeout parameters to the OTP /store-key POST call to mitigate flaky DNS resolution under high concurrency. Mirrors the same resilience settings used in other provisioning scripts.

deploy/operator/provision-shared-host.sh

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 28, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:57 PM UTC · Completed 7:06 PM UTC
Commit: ec21706 · View workflow run →

@qodo-app-for-konflux-ci

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 📜 Skill insights (0)

Context used

Grey Divider


Remediation recommended

1. Retry leaks OTP entries 🐞 Bug ☼ Reliability
Description
The provisioning scripts now use curl --retry-all-errors for the /store-key POST, which can
resend the POST after the OTP server has already stored the key but before the client receives the
token. Since /store-key always generates a new OTP and inserts it into globalMap with no
TTL/deduplication, retries can leave orphan OTP entries that are never removed and can grow memory
usage over time.
Code

deploy/operator/provision-shared-host.sh[212]

+  if ! otp_raw=$(curl --fail --connect-timeout 5 --max-time 30 --retry 3 --retry-all-errors --retry-delay 1 --cacert /tls/tls.crt -XPOST -d "$KEY" https://multi-platform-otp-server.multi-platform-controller.svc.cluster.local/store-key); then
Relevance

⭐⭐⭐ High

PR #844 explicitly fixed orphaned globalMap entries on /store-key write failures; team treats
OTP-map leaks seriously.

PR-#844

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The scripts now retry the /store-key POST with --retry-all-errors, which can duplicate
server-side side effects. The OTP server implementation shows /store-key always creates a new
token and stores it in an in-memory map with no eviction, so duplicated POSTs can leave unredeemed
entries indefinitely.

deploy/operator/provision-shared-host.sh[208-216]
deploy/operator/provision-host-macos.sh[45-53]
deploy/operator/provision-host-windows.sh[46-54]
cmd/otp/otp.go[21-45]
cmd/otp/otp.go[61-86]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`--retry-all-errors` causes curl to retry the `/store-key` POST on *any* failure (including failures that can occur after the server has already stored state), which can create multiple OTP entries server-side while the client only uses the last token.

### Issue Context
The OTP server's `/store-key` handler always creates a new random token and stores the request body under that token in an in-memory global map, and entries are only removed when `/otp` is later called with that exact token. There is no TTL/eviction.

### Fix Focus Areas
- deploy/operator/provision-shared-host.sh[212-212]
- deploy/operator/provision-host-macos.sh[49-49]
- deploy/operator/provision-host-windows.sh[50-50]

### Suggested fix
Replace `--retry-all-errors` with a small bash retry loop that retries **only** on the specific transient curl errors you want to mitigate (e.g., DNS resolution failure exit code 6, optionally connect timeout), and fails fast on HTTP errors (`--fail`) and other permanent failures.

Example pattern (sketch):
- Attempt curl once.
- If it succeeds, break.
- If it fails with exit code 6, sleep 1 and retry up to N times.
- Otherwise, fail immediately.

(Alternative/longer-term: make `/store-key` idempotent or add TTL cleanup in the OTP server.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review

Findings

Medium

  • [logic-error] deploy/operator/otp-utils.sh:14 — Curl exit code 22 is classified as transient ("HTTP 5xx") and retried, but with --fail, exit code 22 fires for any HTTP status >= 400, including non-transient 4xx client errors (400 Bad Request, 403 Forbidden, 404 Not Found). Retrying a 400/404 three times wastes up to ~6 seconds on errors that will never succeed. The comment "HTTP 5xx" will mislead future maintainers about what is actually retried.
    Remediation: Either (a) remove 22 from the retryable list and let it fall through to the immediate-exit * case, or (b) replace --fail with -w '%{http_code}' output parsing to distinguish 4xx from 5xx and only retry on 5xx, or (c) at minimum correct the comment to "HTTP >= 400 (includes 4xx)".

Low

  • [retry-loop-convention] deploy/operator/otp-utils.sh:9 — Retry loop uses {3..1} countdown while other retry loops in the codebase use {10..1}. The difference may be intentional given the different failure mode (OTP server call vs. useradd/userdel), but no comment explains the choice.

  • [scope-creep] deploy/operator/otp-utils.sh — The retry logic targets DNS resolution failures (curl exit code 6) per issue OTP server DNS resolution failure under high concurrency (curl exit code 6) #945, but the PR retries on additional transient errors (7, 22, 28, 35, 56) beyond the specific DNS issue. The expanded scope is reasonable defensive programming but was not explicitly discussed in the linked issue.

  • [sourcing-pattern] deploy/operator/provision-shared-host.sh — This introduces shell script sourcing (. /scripts/otp-utils.sh), which is a new pattern for this codebase. Verify /scripts is the correct mount path in all three Task YAML files.

Previous run

Review

Findings

Critical

  • [logic-error] deploy/operator/otp-utils.sh:19 — The WARNING echo on line 19 writes to stdout. Because curl_otp_store_key is always called via command substitution (otp_raw=$(curl_otp_store_key ...)), all stdout from the function is captured into otp_raw. When a transient failure occurs and curl then succeeds on retry, the captured value contains the WARNING JSON message(s) prepended to the actual OTP token. This corrupted value is then base64-encoded and used as the OTP secret, producing an invalid token. The retry mechanism — the entire purpose of this PR — silently corrupts the OTP token whenever it actually retries. This affects all three provisioning scripts.
    Remediation: Redirect the WARNING echo to stderr by appending >&2, consistent with how the ERROR printf on lines 14 and 22 already directs output to stderr. Change line 19 from echo "{message: ...}" to echo "{message: ...}" >&2.

Low

  • [edge-case] deploy/operator/otp-utils.sh:7 — The OTP_FAIL_MSG variable is used directly as a printf format string (printf "$OTP_FAIL_MSG\n" ...). While the current content only contains an intentional %s specifier, this pattern is fragile — if the message is ever edited to include a literal % character, it would be misinterpreted as a format specifier.
  • [shell-options-consistency] deploy/operator/otp-utils.sh:1 — The new utility file omits set -o verbose, set -eu, and set -o pipefail. Since otp-utils.sh is a sourced library (loaded via . /scripts/otp-utils.sh), it inherits these from the parent script, so this is not a bug — but a brief comment noting the file is meant to be sourced (not executed standalone) would aid maintainability.
  • [error-handling-consistency] deploy/operator/otp-utils.sh:1 — Similarly, the file omits the handle_error() function and ERR trap present in all sibling scripts, which is correct for a sourced library since it inherits the parent's trap.
  • [pr-metadata-consistency] PR body Notes section states "The retry logic is duplicated across three provisioning scripts. Extracting to a shared library would require a new ConfigMap..." but the actual implementation does extract to otp-utils.sh and adds it to existing ConfigMaps. The description appears stale from an earlier design iteration.
Previous run (2)

Looks good to me

Low

  • [abstraction-alignment] deploy/operator/provision-shared-host.sh — The retry logic is duplicated across three provisioning scripts (provision-shared-host.sh, provision-host-macos.sh, provision-host-windows.sh). If retry parameters or error codes need adjustment, all three files must be updated in sync. Consider extracting into a shared function in a follow-up.

Labels: Bug fix adding retry logic to provisioning shell scripts — low-risk, patch-level change

Previous run (3)

Review

Findings

Low

  • [edge-case] deploy/operator/provision-host-macos.sh:61 — On the final loop iteration (attempt=3), when curl fails with a retryable error, the script prints "attempt 3/3. Retrying in 1s..." and sleeps for 1 second, but no retry follows — the loop ends and falls through to the "after 3 attempts" error. This wastes 1 second and logs a misleading message. The same issue exists in provision-host-windows.sh and provision-shared-host.sh. The existing countdown retry patterns in clean-shared-host.sh handle this correctly by checking remaining attempts before printing the retry message.

  • [retry-pattern-consistency] deploy/operator/provision-host-macos.sh:50 — Retry loop uses for attempt in 1 2 3 (count-up) while existing retry loops in provision-shared-host.sh and clean-shared-host.sh use countdown patterns like for i in {10..1}. Minor stylistic inconsistency, though the ascending pattern is simpler for a fixed 3-retry scenario.

  • [implementation-divergence] deploy/operator/provision-host-macos.sh:49 — PR description mentions --retry-all-errors as the correct flag from KONFLUX-14156(#945): add curl retry to OTP server calls #946, but the implementation uses a shell for-loop with selective exit code filtering instead. The shell approach is actually more precise (only retries transient errors 6, 7, 28), but the PR description could be clearer about this design choice.

  • [missing-authorization] — PR references KONFLUX-14156 (Jira) and closes OTP server DNS resolution failure under high concurrency (curl exit code 6) #945. The Jira reference provides traceability but the GitHub issue could not be verified. Minor process note.

Previous run (4)

Looks good to me


Labels: Bug fix adding curl retry/timeout resilience to provisioning scripts.

Comment thread deploy/operator/provision-shared-host.sh Outdated
Comment thread deploy/operator/provision-shared-host.sh Outdated
@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge bug Something isn't working labels Jun 28, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 28, 2026

Copy link
Copy Markdown

🤖 Review · ❌ Terminated · Started 7:59 PM UTC · Ended 8:09 PM UTC
Commit: ec21706 · View workflow run →

@glevi-rh

Copy link
Copy Markdown
Contributor Author

Qodo and fullsend are wrong - ServeHTTP() shows different, we do clean the key.

@qodo-app-for-konflux-ci

Copy link
Copy Markdown

and fullsend are wrong - ServeHTTP() shows different, we do clean the key.

You’re right that ServeHTTP() deletes the OTP entry when the token is redeemed.

The finding isn’t about that path, though — it’s about the retry around /store-key. If the first POST reaches the server and stores an entry, but the client sees a timeout/connection error and retries, the server can end up with an extra stored key/token pair that is never redeemed.

So the leak is not from ServeHTTP() failing to clean up; it’s from duplicate store attempts after a possibly-successful first attempt.

If you want, I can help rephrase the finding more precisely or check whether the retry is actually safe with the current server behavior.

Comment thread deploy/operator/provision-host-macos.sh Outdated
Comment thread deploy/operator/provision-host-macos.sh Outdated
Comment thread deploy/operator/provision-host-macos.sh Outdated
@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed ready-for-merge All reviewers approved — ready to merge labels Jun 28, 2026
@fullsend-ai-review

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 7:59 PM UTC · Completed 8:09 PM UTC
Commit: ec21706 · View workflow run →

@codecov-commenter

codecov-commenter commented Jun 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.85%. Comparing base (f2a6bf5) to head (c64c47c).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #951      +/-   ##
==========================================
- Coverage   76.92%   76.85%   -0.08%     
==========================================
  Files          26       26              
  Lines        2817     2817              
==========================================
- Hits         2167     2165       -2     
- Misses        452      453       +1     
- Partials      198      199       +1     
Flag Coverage Δ
e2e-tests 30.17% <ø> (ø)
unit-tests 73.90% <ø> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.
see 1 file with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f2a6bf5...c64c47c. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 28, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:22 PM UTC · Completed 8:33 PM UTC
Commit: ec21706 · View workflow run →

Comment thread deploy/operator/provision-shared-host.sh Outdated
@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge risk/low PR risk: low semver/patch Semver patch version bump and removed ready-for-merge All reviewers approved — ready to merge labels Jun 28, 2026
@qodo-app-for-konflux-ci

Copy link
Copy Markdown

CI Feedback 🧐

A test triggered by this PR failed. Here is an AI-generated analysis of the failure:

Action: Run on Ubuntu

Failed stage: Configure AWS Credentials [❌]

Failed test name: ""

Failure summary:

The workflow failed due to infrastructure/auth and missing build artifacts rather than a failing
test:
- AWS credentials setup via OIDC failed: the action could not assume
arn:aws:iam::418272753558:role/multi-platform-github-action, first with network timeouts to AWS STS
(connect ETIMEDOUT ...:443), then repeatedly with Token expired: current date/time ... must be
before the expiration date/time ... (lines ~1817-1842). This prevented AWS-dependent steps from
running correctly.
- Pulling the container image
quay.io/konflux-ci/konflux-devprod/coverport-cli:latest failed due to registry network timeouts
(dial tcp ...:443: i/o timeout) (lines ~1869-1873).
- Codecov upload reported no coverage output:
Found 0 coverage files to reportError: No coverage reports found (lines ~2205-2209). (This may or
may not have been configured to fail the job, but it indicates missing/failed coverage generation.)

- The job ultimately failed with exit code 127 because cleanup steps attempted to run
./out/devsetup, but the file was not present: /...sh: line 1: ./out/devsetup: No such file or
directory (lines ~2282-2284, repeated again at ~2305-2306 and ~2328-2329).

Relevant error logs:
1:  ##[group]Runner Image Provisioner
2:  Hosted Compute Agent
...

162:  �[36;1m�[0m
163:  �[36;1m  sudo rm -rf /opt/ghc || true�[0m
164:  �[36;1m  sudo rm -rf /usr/local/.ghcup || true�[0m
165:  �[36;1m  �[0m
166:  �[36;1m  AFTER=$(getAvailableSpace)�[0m
167:  �[36;1m  SAVED=$((AFTER-BEFORE))�[0m
168:  �[36;1m  printSavedSpace $SAVED "Haskell runtime"�[0m
169:  �[36;1mfi�[0m
170:  �[36;1m�[0m
171:  �[36;1m# Option: Remove large packages�[0m
172:  �[36;1m# REF: https://github.com/apache/flink/blob/master/tools/azure-pipelines/free_disk_space.sh�[0m
173:  �[36;1m�[0m
174:  �[36;1mif [[ true == 'true' ]]; then�[0m
175:  �[36;1m  BEFORE=$(getAvailableSpace)�[0m
176:  �[36;1m  �[0m
177:  �[36;1m  sudo apt-get remove -y '^aspnetcore-.*' || echo "::warning::The command [sudo apt-get remove -y '^aspnetcore-.*'] failed to complete successfully. Proceeding..."�[0m
178:  �[36;1m  sudo apt-get remove -y '^dotnet-.*' --fix-missing || echo "::warning::The command [sudo apt-get remove -y '^dotnet-.*' --fix-missing] failed to complete successfully. Proceeding..."�[0m
179:  �[36;1m  sudo apt-get remove -y '^llvm-.*' --fix-missing || echo "::warning::The command [sudo apt-get remove -y '^llvm-.*' --fix-missing] failed to complete successfully. Proceeding..."�[0m
180:  �[36;1m  sudo apt-get remove -y 'php.*' --fix-missing || echo "::warning::The command [sudo apt-get remove -y 'php.*' --fix-missing] failed to complete successfully. Proceeding..."�[0m
181:  �[36;1m  sudo apt-get remove -y '^mongodb-.*' --fix-missing || echo "::warning::The command [sudo apt-get remove -y '^mongodb-.*' --fix-missing] failed to complete successfully. Proceeding..."�[0m
182:  �[36;1m  sudo apt-get remove -y '^mysql-.*' --fix-missing || echo "::warning::The command [sudo apt-get remove -y '^mysql-.*' --fix-missing] failed to complete successfully. Proceeding..."�[0m
183:  �[36;1m  sudo apt-get remove -y azure-cli google-chrome-stable firefox powershell mono-devel libgl1-mesa-dri --fix-missing || echo "::warning::The command [sudo apt-get remove -y azure-cli google-chrome-stable firefox powershell mono-devel libgl1-mesa-dri --fix-missing] failed to complete successfully. Proceeding..."�[0m
184:  �[36;1m  sudo apt-get remove -y google-cloud-sdk --fix-missing || echo "::debug::The command [sudo apt-get remove -y google-cloud-sdk --fix-missing] failed to complete successfully. Proceeding..."�[0m
185:  �[36;1m  sudo apt-get remove -y google-cloud-cli --fix-missing || echo "::debug::The command [sudo apt-get remove -y google-cloud-cli --fix-missing] failed to complete successfully. Proceeding..."�[0m
186:  �[36;1m  sudo apt-get autoremove -y || echo "::warning::The command [sudo apt-get autoremove -y] failed to complete successfully. Proceeding..."�[0m
187:  �[36;1m  sudo apt-get clean || echo "::warning::The command [sudo apt-get clean] failed to complete successfully. Proceeding..."�[0m
188:  �[36;1m�[0m
...

978:  Package 'php-sql-formatter' is not installed, so not removed
979:  Package 'php8.3-ssh2' is not installed, so not removed
980:  Package 'php-ssh2-all-dev' is not installed, so not removed
981:  Package 'php8.3-stomp' is not installed, so not removed
982:  Package 'php-stomp-all-dev' is not installed, so not removed
983:  Package 'php-swiftmailer' is not installed, so not removed
984:  Package 'php-symfony' is not installed, so not removed
985:  Package 'php-symfony-asset' is not installed, so not removed
986:  Package 'php-symfony-asset-mapper' is not installed, so not removed
987:  Package 'php-symfony-browser-kit' is not installed, so not removed
988:  Package 'php-symfony-clock' is not installed, so not removed
989:  Package 'php-symfony-debug-bundle' is not installed, so not removed
990:  Package 'php-symfony-doctrine-bridge' is not installed, so not removed
991:  Package 'php-symfony-dom-crawler' is not installed, so not removed
992:  Package 'php-symfony-dotenv' is not installed, so not removed
993:  Package 'php-symfony-error-handler' is not installed, so not removed
994:  Package 'php-symfony-event-dispatcher' is not installed, so not removed
...

1172:  Package 'php-twig-html-extra' is not installed, so not removed
1173:  Package 'php-twig-i18n-extension' is not installed, so not removed
1174:  Package 'php-twig-inky-extra' is not installed, so not removed
1175:  Package 'php-twig-intl-extra' is not installed, so not removed
1176:  Package 'php-twig-markdown-extra' is not installed, so not removed
1177:  Package 'php-twig-string-extra' is not installed, so not removed
1178:  Package 'php8.3-uopz' is not installed, so not removed
1179:  Package 'php-uopz-all-dev' is not installed, so not removed
1180:  Package 'php8.3-uploadprogress' is not installed, so not removed
1181:  Package 'php-uploadprogress-all-dev' is not installed, so not removed
1182:  Package 'php8.3-uuid' is not installed, so not removed
1183:  Package 'php-uuid-all-dev' is not installed, so not removed
1184:  Package 'php-validate' is not installed, so not removed
1185:  Package 'php-vlucas-phpdotenv' is not installed, so not removed
1186:  Package 'php-voku-portable-ascii' is not installed, so not removed
1187:  Package 'php-wmerrors' is not installed, so not removed
1188:  Package 'php-xdebug-all-dev' is not installed, so not removed
...

1803:  with:
1804:  role-to-assume: arn:aws:iam::418272753558:role/multi-platform-github-action
1805:  aws-region: us-east-1
1806:  role-duration-seconds: 3600
1807:  audience: sts.amazonaws.com
1808:  env:
1809:  AWS_ROLE_ARN: arn:aws:iam::418272753558:role/multi-platform-github-action
1810:  AWS_REGION: us-east-1
1811:  AWS_ROLE_DURATION: 3600
1812:  INSTANCE_TAG: 28334143596-development
1813:  S3_LOGS_BUCKET: otelcol-logs
1814:  KIND_EXPERIMENTAL_PROVIDER: podman
1815:  E2E_DEBUG_LOG_DIR: /home/runner/work/multi-platform-controller/multi-platform-controller/e2e-debug-logs
1816:  ##[endgroup]
1817:  Assuming role with OIDC
1818:  Retry AssumeRole: attempt 1 of 12 failed: Could not assume role with OIDC: connect ETIMEDOUT 13.217.78.225:443. Retrying after 37ms.
1819:  Assuming role with OIDC
1820:  Retry AssumeRole: attempt 2 of 12 failed: Could not assume role with OIDC: connect ETIMEDOUT 13.217.78.216:443. Retrying after 60ms.
1821:  Assuming role with OIDC
1822:  Retry AssumeRole: attempt 3 of 12 failed: Could not assume role with OIDC: connect ETIMEDOUT 13.217.79.62:443. Retrying after 150ms.
1823:  Assuming role with OIDC
1824:  Retry AssumeRole: attempt 4 of 12 failed: Could not assume role with OIDC: Token expired: current date/time 1782677707 must be before the expiration date/time 1782676957. Retrying after 259ms.
1825:  Assuming role with OIDC
1826:  Retry AssumeRole: attempt 5 of 12 failed: Could not assume role with OIDC: Token expired: current date/time 1782677708 must be before the expiration date/time 1782676957. Retrying after 783ms.
1827:  Assuming role with OIDC
1828:  Retry AssumeRole: attempt 6 of 12 failed: Could not assume role with OIDC: Token expired: current date/time 1782677709 must be before the expiration date/time 1782676957. Retrying after 1496ms.
1829:  Assuming role with OIDC
1830:  Retry AssumeRole: attempt 7 of 12 failed: Could not assume role with OIDC: Token expired: current date/time 1782677710 must be before the expiration date/time 1782676957. Retrying after 2561ms.
1831:  Assuming role with OIDC
1832:  Retry AssumeRole: attempt 8 of 12 failed: Could not assume role with OIDC: Token expired: current date/time 1782677713 must be before the expiration date/time 1782676957. Retrying after 3385ms.
1833:  Assuming role with OIDC
1834:  Retry AssumeRole: attempt 9 of 12 failed: Could not assume role with OIDC: Token expired: current date/time 1782677717 must be before the expiration date/time 1782676957. Retrying after 7673ms.
1835:  Assuming role with OIDC
1836:  Retry AssumeRole: attempt 10 of 12 failed: Could not assume role with OIDC: Token expired: current date/time 1782677725 must be before the expiration date/time 1782676957. Retrying after 19731ms.
1837:  Assuming role with OIDC
1838:  Retry AssumeRole: attempt 11 of 12 failed: Could not assume role with OIDC: Token expired: current date/time 1782677745 must be before the expiration date/time 1782676957. Retrying after 14592ms.
1839:  Assuming role with OIDC
1840:  Retry AssumeRole: attempt 12 of 12 failed: Could not assume role with OIDC: Token expired: current date/time 1782677759 must be before the expiration date/time 1782676957. Retrying after 1012ms.
1841:  Retry AssumeRole: reached max retries (12); giving up.
1842:  ##[error]Could not assume role with OIDC: Token expired: current date/time 1782677759 must be before the expiration date/time 1782676957
1843:  ##[group]Run mkdir -p coverage-output && chmod 777 coverage-output
...

1855:  �[36;1m    --test-name=e2e-tests \�[0m
1856:  �[36;1m    --output=/workspace/coverage-output || true�[0m
1857:  shell: /usr/bin/bash -e {0}
1858:  env:
1859:  AWS_ROLE_ARN: arn:aws:iam::418272753558:role/multi-platform-github-action
1860:  AWS_REGION: us-east-1
1861:  AWS_ROLE_DURATION: 3600
1862:  INSTANCE_TAG: 28334143596-development
1863:  S3_LOGS_BUCKET: otelcol-logs
1864:  KIND_EXPERIMENTAL_PROVIDER: podman
1865:  E2E_DEBUG_LOG_DIR: /home/runner/work/multi-platform-controller/multi-platform-controller/e2e-debug-logs
1866:  AWS_DEFAULT_REGION: us-east-1
1867:  ##[endgroup]
1868:  cp: cannot stat '/home/runner/.kube/config': No such file or directory
1869:  Trying to pull quay.io/konflux-ci/konflux-devprod/coverport-cli:latest...
1870:  time="2026-06-28T20:22:01Z" level=warning msg="Failed, retrying in 1s ... (1/3). Error: initializing source docker://quay.io/konflux-ci/konflux-devprod/coverport-cli:latest: pinging container registry quay.io: Get \"https://quay.io/v2/\": dial tcp 3.208.207.110:443: i/o timeout"
1871:  time="2026-06-28T20:23:02Z" level=warning msg="Failed, retrying in 1s ... (2/3). Error: initializing source docker://quay.io/konflux-ci/konflux-devprod/coverport-cli:latest: pinging container registry quay.io: Get \"https://quay.io/v2/\": dial tcp 54.152.82.185:443: i/o timeout"
1872:  time="2026-06-28T20:24:03Z" level=warning msg="Failed, retrying in 1s ... (3/3). Error: initializing source docker://quay.io/konflux-ci/konflux-devprod/coverport-cli:latest: pinging container registry quay.io: Get \"https://quay.io/v2/\": dial tcp 18.215.114.174:443: i/o timeout"
1873:  Error: initializing source docker://quay.io/konflux-ci/konflux-devprod/coverport-cli:latest: pinging container registry quay.io: Get "https://quay.io/v2/": dial tcp 13.216.176.160:443: i/o timeout
1874:  ##[group]Run codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354
1875:  with:
1876:  use_oidc: true
1877:  flags: e2e-tests
1878:  directory: coverage-output
1879:  fail_ci_if_error: false
1880:  disable_file_fixes: false
...

1909:  �[36;1mfor cmd in bash git curl; do�[0m
1910:  �[36;1m  if ! command -v "$cmd" >/dev/null 2>&1; then�[0m
1911:  �[36;1m    missing_deps="$missing_deps $cmd"�[0m
1912:  �[36;1m  fi�[0m
1913:  �[36;1mdone�[0m
1914:  �[36;1m�[0m
1915:  �[36;1m# Check for gpg only if validation is not being skipped�[0m
1916:  �[36;1mif [ "$INPUT_SKIP_VALIDATION" != "true" ]; then�[0m
1917:  �[36;1m  if ! command -v gpg >/dev/null 2>&1; then�[0m
1918:  �[36;1m    missing_deps="$missing_deps gpg"�[0m
1919:  �[36;1m  fi�[0m
1920:  �[36;1mfi�[0m
1921:  �[36;1m�[0m
1922:  �[36;1m# Report missing required dependencies�[0m
1923:  �[36;1mif [ -n "$missing_deps" ]; then�[0m
1924:  �[36;1m  echo "Error: The following required dependencies are missing:$missing_deps"�[0m
1925:  �[36;1m  echo "Please install these dependencies before using this action."�[0m
...

2126:  CC_SHA: 326fdde15e17f4fb7f604194ccc0585a86c6a018
2127:  CC_PR: 
2128:  CC_BASE_SHA: 
2129:  CC_BINARY: 
2130:  CC_BUILD: 
2131:  CC_BUILD_URL: 
2132:  CC_CODE: 
2133:  CC_DIR: coverage-output
2134:  CC_DISABLE_FILE_FIXES: false
2135:  CC_DISABLE_SEARCH: false
2136:  CC_DISABLE_TELEM: false
2137:  CC_DRY_RUN: false
2138:  CC_ENTERPRISE_URL: 
2139:  CC_ENV: 
2140:  CC_EXCLUDES: 
2141:  CC_FAIL_ON_ERROR: false
2142:  CC_FILES: 
...

2193:  �[0;32m ->�[0m Downloading �[0;36mhttps://cli.codecov.io/latest/linux/codecov.SHA256SUM.sig�[0m
2194:  gpg: Signature made Tue Apr 21 19:28:03 2026 UTC
2195:  gpg:                using RSA key 27034E7FDB850E0BBC2C62FF806BB28AED779869
2196:  gpg: Can't check signature: No public key
2197:  �[0;31m==> Could not verify signature. Please contact Codecov if problem continues�[0m
2198:  codecov: OK
2199:  �[0;32m==>�[0m CLI integrity verified
2200:  �[0;32m ->�[0m Token length: 2066
2201:  �[0;32m==>�[0m Running upload-coverage
2202:  �[0;36m./codecov  upload-coverage -t <redacted> --git-service github --sha 326fdde15e17f4fb7f604194ccc0585a86c6a018 --dir coverage-output --flag e2e-tests --gcov-executable gcov�[0m
2203:  info - 2026-06-28 20:29:33,323 -- ci service found: github-actions
2204:  warning - 2026-06-28 20:29:33,366 -- xcrun is not installed or can't be found.
2205:  warning - 2026-06-28 20:29:33,367 -- No gcov data found.
2206:  warning - 2026-06-28 20:29:33,368 -- coverage.py is not installed or can't be found.
2207:  info - 2026-06-28 20:29:33,383 -- Found 0 coverage files to report
2208:  Error: No coverage reports found. Please make sure you're generating reports successfully.
2209:  �[0;31m==> Failed to run upload-coverage�[0m
2210:  ##[group]Run actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
...

2243:  AWS_ROLE_ARN: arn:aws:iam::418272753558:role/multi-platform-github-action
2244:  AWS_REGION: us-east-1
2245:  AWS_ROLE_DURATION: 3600
2246:  INSTANCE_TAG: 28334143596-development
2247:  S3_LOGS_BUCKET: otelcol-logs
2248:  KIND_EXPERIMENTAL_PROVIDER: podman
2249:  E2E_DEBUG_LOG_DIR: /home/runner/work/multi-platform-controller/multi-platform-controller/e2e-debug-logs
2250:  AWS_DEFAULT_REGION: us-east-1
2251:  CC_FORK: false
2252:  CC_TOKEN: "***"
2253:  CC_BRANCH: 
2254:  CC_SHA: 326fdde15e17f4fb7f604194ccc0585a86c6a018
2255:  CC_PR: 
2256:  ##[endgroup]
2257:  Assuming role with OIDC
2258:  Retry AssumeRole: attempt 1 of 12 failed: Could not assume role with OIDC: connect ETIMEDOUT 44.213.78.45:443. Retrying after 0ms.
2259:  Assuming role with OIDC
...

2268:  INSTANCE_TAG: 28334143596-development
2269:  S3_LOGS_BUCKET: otelcol-logs
2270:  KIND_EXPERIMENTAL_PROVIDER: podman
2271:  E2E_DEBUG_LOG_DIR: /home/runner/work/multi-platform-controller/multi-platform-controller/e2e-debug-logs
2272:  AWS_DEFAULT_REGION: us-east-1
2273:  CC_FORK: false
2274:  CC_TOKEN: "***"
2275:  CC_BRANCH: 
2276:  CC_SHA: 326fdde15e17f4fb7f604194ccc0585a86c6a018
2277:  CC_PR: 
2278:  AWS_ACCESS_KEY_ID: ***
2279:  AWS_SECRET_ACCESS_KEY: ***
2280:  AWS_SESSION_TOKEN: ***
2281:  ##[endgroup]
2282:  /home/runner/work/_temp/2b01fa34-7735-4613-9d83-f4c0f1e039eb.sh: line 1: ./out/devsetup: No such file or directory
2283:  ##[error]Process completed with exit code 127.
2284:  ##[group]Run ./out/devsetup cleanup-s3-logs 28334143596
...

2291:  INSTANCE_TAG: 28334143596-development
2292:  S3_LOGS_BUCKET: otelcol-logs
2293:  KIND_EXPERIMENTAL_PROVIDER: podman
2294:  E2E_DEBUG_LOG_DIR: /home/runner/work/multi-platform-controller/multi-platform-controller/e2e-debug-logs
2295:  AWS_DEFAULT_REGION: us-east-1
2296:  CC_FORK: false
2297:  CC_TOKEN: "***"
2298:  CC_BRANCH: 
2299:  CC_SHA: 326fdde15e17f4fb7f604194ccc0585a86c6a018
2300:  CC_PR: 
2301:  AWS_ACCESS_KEY_ID: ***
2302:  AWS_SECRET_ACCESS_KEY: ***
2303:  AWS_SESSION_TOKEN: ***
2304:  ##[endgroup]
2305:  /home/runner/work/_temp/7a3d8d4d-2d85-4dc6-b3c8-c42b639f7df9.sh: line 1: ./out/devsetup: No such file or directory
2306:  ##[error]Process completed with exit code 127.
2307:  ##[group]Run ./out/devsetup cleanup-keypair 28334143596
...

2314:  INSTANCE_TAG: 28334143596-development
2315:  S3_LOGS_BUCKET: otelcol-logs
2316:  KIND_EXPERIMENTAL_PROVIDER: podman
2317:  E2E_DEBUG_LOG_DIR: /home/runner/work/multi-platform-controller/multi-platform-controller/e2e-debug-logs
2318:  AWS_DEFAULT_REGION: us-east-1
2319:  CC_FORK: false
2320:  CC_TOKEN: "***"
2321:  CC_BRANCH: 
2322:  CC_SHA: 326fdde15e17f4fb7f604194ccc0585a86c6a018
2323:  CC_PR: 
2324:  AWS_ACCESS_KEY_ID: ***
2325:  AWS_SECRET_ACCESS_KEY: ***
2326:  AWS_SESSION_TOKEN: ***
2327:  ##[endgroup]
2328:  /home/runner/work/_temp/fc99cca7-5625-4874-83f3-6674b17b94a3.sh: line 1: ./out/devsetup: No such file or directory
2329:  ##[error]Process completed with exit code 127.
2330:  Post job cleanup.

@meyrevived meyrevived left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better and more detailed than what fullsend created, but there are a couple of things here

Comment thread deploy/operator/provision-shared-host.sh Outdated
Comment thread deploy/operator/provision-host-macos.sh Outdated
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 29, 2026

Copy link
Copy Markdown

🤖 Review · ⚠️ Cancelled · Started 8:03 AM UTC · Ended 8:11 AM UTC
Commit: ec21706 · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 8:14 AM UTC · Completed 8:27 AM UTC
Commit: ec21706 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

Comment thread deploy/operator/otp-utils.sh Outdated
Comment thread deploy/operator/otp-utils.sh Outdated
Comment thread deploy/operator/otp-utils.sh
Comment thread deploy/operator/otp-utils.sh
@fullsend-ai-review fullsend-ai-review Bot removed the ready-for-merge All reviewers approved — ready to merge label Jun 29, 2026
@glevi-rh
glevi-rh requested a review from meyrevived June 29, 2026 09:32
Comment thread deploy/operator/otp-utils.sh Outdated
Comment thread deploy/operator/otp-utils.sh Outdated
Comment thread deploy/operator/otp-utils.sh
Comment thread deploy/operator/otp-utils.sh
…calls

Under high concurrency (200 concurrent RPM builds), the OTP server
DNS name intermittently fails to resolve, causing curl to exit with
code 6 (CURLE_COULDNT_RESOLVE_HOST) and the build step to fail.
Observed as a 1% failure rate (2/200) on stone-stg-rh01.

Add a shared otp-utils.sh with curl_otp_store_key() that wraps curl
in a retry loop, retrying up to 3 times on transient errors only
(curl exit codes 6, 7, 22, 28, 35, 56). All other errors fail
immediately. The shared script is added to each provisioning
ConfigMap via kustomization.yaml and sourced at script start.

The empty-token check is also moved into the shared function to
reduce duplication across the provisioning scripts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Gal Levi <glevi@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 29, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 12:17 PM UTC · Completed 12:28 PM UTC
Commit: ec21706 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

Comment thread deploy/operator/otp-utils.sh
Comment thread deploy/operator/otp-utils.sh
@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jun 29, 2026
@glevi-rh
glevi-rh requested a review from meyrevived June 29, 2026 19:47

@meyrevived meyrevived left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@glevi-rh
glevi-rh added this pull request to the merge queue Jun 30, 2026
Merged via the queue into main with commit a5285b3 Jun 30, 2026
31 checks passed
@glevi-rh
glevi-rh deleted the otp-curl-retry branch June 30, 2026 13:14
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jun 30, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ❌ Failure · Started 1:17 PM UTC · Completed 1:27 PM UTC
Commit: ec21706 · View workflow run →

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working requires-manual-review Review requires human judgment risk/low PR risk: low semver/patch Semver patch version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OTP server DNS resolution failure under high concurrency (curl exit code 6)

3 participants