-
Notifications
You must be signed in to change notification settings - Fork 406
chore: Run CI on changed files; add retries & gating #1614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,20 +2,48 @@ name: Lint Backend | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pull_request: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| paths: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'src/**/*.py' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'tests/**/*.py' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'pyproject.toml' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'uv.lock' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - '.github/workflows/lint-backend.yml' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| merge_group: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Cancel in-flight runs on the same PR when a new push lands. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| concurrency: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| group: lint-backend-${{ github.ref }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cancel-in-progress: true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| changes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| outputs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: ${{ steps.decision.outputs.run }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: dorny/paths-filter@v3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id: filter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if: github.event_name == 'pull_request' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| filters: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| relevant: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'src/**/*.py' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'tests/**/*.py' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'pyproject.toml' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'uv.lock' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - '.github/workflows/lint-backend.yml' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - id: decision | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Skip on merge_group: lint runs on changed files only, so | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # re-running on the queued ref would just re-check the same set | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # the PR already passed. The required job below still reports | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # green so the merge queue is not blocked. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "${{ github.event_name }}" = "merge_group" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "run=false" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+32
to
+37
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif [ "${{ steps.filter.outputs.relevant }}" = "true" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "run=true" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "run=false" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lint: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| needs: changes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if: needs.changes.outputs.run == 'true' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Ruff and mypy on changed files | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -87,3 +115,17 @@ jobs: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "${#test_files[@]}" -gt 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| uv run mypy "${test_files[@]}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| needs: lint | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if: always() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Verify lint result | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result="${{ needs.lint.result }}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "lint job did not succeed: $result" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "lint result: $result (success or skipped — passing)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+119
to
+131
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Include
Proposed fix required:
- needs: lint
+ needs: [changes, lint]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify lint result
run: |
- result="${{ needs.lint.result }}"
- if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then
- echo "lint job did not succeed: $result"
+ changes_result="${{ needs.changes.result }}"
+ lint_result="${{ needs.lint.result }}"
+ if [ "$changes_result" = "failure" ] || [ "$changes_result" = "cancelled" ]; then
+ echo "changes job did not succeed: $changes_result"
+ exit 1
+ fi
+ if [ "$lint_result" = "failure" ] || [ "$lint_result" = "cancelled" ]; then
+ echo "lint job did not succeed: $lint_result"
exit 1
fi
- echo "lint result: $result (success or skipped — passing)"
+ echo "changes=$changes_result, lint=$lint_result (success or skipped — passing)"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,12 +2,36 @@ name: Frontend Lint | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pull_request: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| paths: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'frontend/**' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - '.github/workflows/lint-frontend.yml' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| merge_group: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| changes: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| outputs: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: ${{ steps.decision.outputs.run }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - uses: dorny/paths-filter@v3 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+13
to
+14
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Show the relevant workflow section with line numbers
FILE=".github/workflows/lint-frontend.yml"
if [ ! -f "$FILE" ]; then
echo "Missing $FILE"
exit 1
fi
echo "---- $FILE (lines 1-80) ----"
nl -ba "$FILE" | sed -n '1,80p'
echo "---- Find all checkout and paths-filter usages ----"
rg -n "uses:\s*(actions/checkout|dorny/paths-filter)@" "$FILE" || true
rg -n "persist-credentials" "$FILE" || trueRepository: langflow-ai/openrag Length of output: 184 🏁 Script executed: #!/bin/bash
set -euo pipefail
FILE=".github/workflows/lint-frontend.yml"
if [ ! -f "$FILE" ]; then
echo "Missing $FILE"
exit 1
fi
echo "---- $FILE (first 120 lines with numbers) ----"
# Use cat -n since nl is missing
cat -n "$FILE" | sed -n '1,120p'
echo "---- Find all checkout and paths-filter usages ----"
if command -v rg >/dev/null 2>&1; then
rg -n "uses:\s*(actions/checkout|dorny/paths-filter)@" "$FILE" || true
rg -n "persist-credentials" "$FILE" || true
else
grep -nE "uses:\s*(actions/checkout|dorny/paths-filter)@" "$FILE" || true
grep -n "persist-credentials" "$FILE" || true
fiRepository: langflow-ai/openrag Length of output: 3197 🌐 Web query:
💡 Result: The actions/checkout GitHub Action has a default value of true for the persist-credentials input [1][2][3]. When persist-credentials is set to its default (true), the action configures the authentication token (such as GITHUB_TOKEN) or SSH key in the local git configuration of the checked-out repository [1][4][3]. This allows subsequent scripts within the same job to execute authenticated git commands directly [1][2]. The action is designed to remove these credentials from the local git configuration during the post-job cleanup phase [1][3]. However, security concerns have been raised regarding this behavior [5][6]. Because the credentials are written to the repository's.git/config file, they become accessible to any steps or processes running in the job [7][6]. In scenarios where artifacts are created and uploaded from the workspace, these credentials can potentially be inadvertently leaked [6]. To improve security and adhere to the principle of least privilege, it is recommended to explicitly set persist-credentials: false for any workflow steps that do not require authenticated git push capabilities [7][6]. Example usage to disable this behavior: - uses: actions/checkout@v4 with: persist-credentials: false Citations:
🌐 Web query:
💡 Result: Pinning GitHub Actions to a full-length commit SHA is a recommended security best practice to ensure workflow immutability and protect against supply-chain attacks [1][2][3]. Why Pinning to SHA is Required GitHub Actions tags (e.g., Citations:
Pin workflow actions and set
Proposed hardening patch- - uses: actions/checkout@v4
- - uses: dorny/paths-filter@v3
+ - uses: actions/checkout@<pinned-sha>
+ with:
+ persist-credentials: false
+ - uses: dorny/paths-filter@<pinned-sha>🧰 Tools🪛 zizmor (1.25.2)[warning] 13-13: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [error] 13-13: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) [error] 14-14: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id: filter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if: github.event_name == 'pull_request' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| filters: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| relevant: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - 'frontend/**' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - '.github/workflows/lint-frontend.yml' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - id: decision | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "${{ github.event_name }}" = "merge_group" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "run=true" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif [ "${{ steps.filter.outputs.relevant }}" = "true" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "run=true" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "run=false" >> "$GITHUB_OUTPUT" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| biome: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| needs: changes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if: needs.changes.outputs.run == 'true' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: Biome | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -48,3 +72,16 @@ jobs: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: TypeScript type check | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| working-directory: frontend | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: npm run typecheck | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| needs: biome | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if: always() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - name: Verify biome result | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run: | | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result="${{ needs.biome.result }}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "biome job did not succeed: $result" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "biome result: $result (success or skipped — passing)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+75
to
+87
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fail the required job when Current guard only inspects Proposed fix required:
- needs: biome
+ needs: [changes, biome]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify biome result
run: |
- result="${{ needs.biome.result }}"
- if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then
- echo "biome job did not succeed: $result"
+ changes_result="${{ needs.changes.result }}"
+ biome_result="${{ needs.biome.result }}"
+ if [ "$changes_result" = "failure" ] || [ "$changes_result" = "cancelled" ]; then
+ echo "changes job did not succeed: $changes_result"
+ exit 1
+ fi
+ if [ "$biome_result" = "failure" ] || [ "$biome_result" = "cancelled" ]; then
+ echo "biome job did not succeed: $biome_result"
exit 1
fi
- echo "biome result: $result (success or skipped — passing)"
+ echo "changes=$changes_result, biome=$biome_result (success or skipped — passing)"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,18 +2,16 @@ name: E2E Tests | |
|
|
||
| on: | ||
| pull_request: | ||
| paths: | ||
| - 'src/**' | ||
| - 'frontend/**' | ||
| - 'tests/**' | ||
| - 'scripts/**' | ||
| - 'flows/**' | ||
| - 'docker-compose.yml' | ||
| - 'Dockerfile*' | ||
| - 'Makefile' | ||
| - '.github/workflows/test-e2e.yml' | ||
| merge_group: | ||
| workflow_dispatch: | ||
|
|
||
| # Serialize E2E and Integration on the same PR/queue ref. They share runner | ||
| # pool and Docker resources; running them concurrently inflates the flake | ||
| # rate. Different PRs have different refs and run in parallel as usual. | ||
| concurrency: | ||
| group: heavy-tests-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| env: | ||
| NODE_VERSION: "22" | ||
| PYTHON_VERSION: "3.13" | ||
|
|
@@ -23,7 +21,40 @@ env: | |
| PLAYWRIGHT_VERSION: "1.57.0" | ||
|
|
||
| jobs: | ||
| changes: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| run: ${{ steps.decision.outputs.run }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: dorny/paths-filter@v3 | ||
|
Comment on lines
+29
to
+30
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect the target workflow with line numbers around the reported locations
echo "=== test-e2e.yml lines 1-200 (for context) ==="
nl -ba .github/workflows/test-e2e.yml | sed -n '1,200p'
echo "=== test-e2e.yml: uses: lines ==="
rg -n "^\s*- uses: " .github/workflows/test-e2e.yml
echo "=== Search other workflows for similar action usage patterns ==="
rg -n --glob ".github/workflows/*.yml" -S "actions/checkout@|dorny/paths-filter@|nick-fields/retry@" .github/workflows || true
echo "=== Search for any pinned SHAs for these actions across workflows ==="
rg -n --glob ".github/workflows/*.yml" -S "actions/checkout@([0-9a-f]{40})|dorny/paths-filter@([0-9a-f]{40})|nick-fields/retry@([0-9a-f]{40})" .github/workflows || true
echo "=== Check if repository has any workflow hardening policy docs ==="
ls -la .github || true
ls -la .github/workflows || true
rg -n "pinn?ed|immutable SHAs|supply chain|workflow policy" .github || trueRepository: langflow-ai/openrag Length of output: 171 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== test-e2e.yml: first 200 lines (with line numbers) ==="
awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/test-e2e.yml | sed -n '1,200p'
echo "=== test-e2e.yml: all lines with '- uses:' ==="
awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/test-e2e.yml | rg -n "^\s*\d+\t-\s+uses:"
echo "=== Search other workflows for actions/checkout@, dorny/paths-filter@, nick-fields/retry@ ==="
rg -n --glob ".github/workflows/*.yml" -S "actions/checkout@|dorny/paths-filter@|nick-fields/retry@" .github/workflows || true
echo "=== Search for pinned SHAs for these actions across workflows ==="
rg -n --glob ".github/workflows/*.yml" -S "actions/checkout@[0-9a-f]{40}|dorny/paths-filter@[0-9a-f]{40}|nick-fields/retry@[0-9a-f]{40}" .github/workflows || true
echo "=== Check for any existing workflow hardening policy docs ==="
rg -n "pinn?ed|immutable SHAs|supply chain|workflow policy" .github || true
ls -la .github || true
ls -la .github/workflows || trueRepository: langflow-ai/openrag Length of output: 8366 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== test-e2e.yml: all '- uses:' lines ==="
awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/test-e2e.yml | rg '^\s*[0-9]+\t-\s+uses:' || true
echo "=== Other workflows: occurrences of checkout/paths-filter/retry ==="
rg -n --glob ".github/workflows/*.yml" -S "(actions/checkout@|dorny/paths-filter@|nick-fields/retry@)" .github/workflows || true
echo "=== Other workflows: pinned SHA occurrences for those actions ==="
rg -n --glob ".github/workflows/*.yml" -S "(actions/checkout@[0-9a-f]{40}|dorny/paths-filter@[0-9a-f]{40}|nick-fields/retry@[0-9a-f]{40})" .github/workflows || true
echo "=== Search for supply-chain pinning policy/docs ==="
rg -n "pinn?ed|immutable SHAs|supply chain|workflow policy|dependabot|renovate.*workflow|actions/checkout@.*[0-9a-f]{40}" .github || trueRepository: langflow-ai/openrag Length of output: 3174 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== Any pinned SHAs for actions/checkout/dorny/paths-filter/nick-fields/retry across workflows? ==="
rg -n --glob ".github/workflows/*.yml" -S "actions/checkout@[0-9a-f]{40}|dorny/paths-filter@[0-9a-f]{40}|nick-fields/retry@[0-9a-f]{40}" .github/workflows || true
echo "=== Any mention of pinning/immutable SHAs/workflow policy/dependabot/renovate in .github ==="
rg -n "pinn?ed|immutable SHAs|supply chain|workflow policy|dependabot|renovate" .github || true
echo "=== Check test-e2e.yml for submodules/persist-credentials/token usage ==="
rg -n "submodule|persist-credentials|token:|GITHUB_TOKEN" .github/workflows/test-e2e.yml || true
echo "=== Check test-e2e.yml for git commands needing auth ==="
rg -n "\bgit (clone|fetch|checkout|submodule|push|tag|config)\b" .github/workflows/test-e2e.yml || trueRepository: langflow-ai/openrag Length of output: 387 Pin CI action refs to immutable commit SHAs (actions/checkout, dorny/paths-filter, nick-fields/retry) In
Proposed hardening patch- - uses: actions/checkout@v4
- - uses: dorny/paths-filter@v3
+ - uses: actions/checkout@<pinned-sha>
+ with:
+ persist-credentials: false
+ - uses: dorny/paths-filter@<pinned-sha>
...
- - name: Run Playwright tests
- uses: nick-fields/retry@v3
+ - name: Run Playwright tests
+ uses: nick-fields/retry@<pinned-sha>🧰 Tools🪛 zizmor (1.25.2)[warning] 29-29: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [error] 29-29: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) [error] 30-30: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI Agents |
||
| id: filter | ||
| if: github.event_name == 'pull_request' | ||
| with: | ||
| filters: | | ||
| relevant: | ||
| - 'src/**' | ||
| - 'frontend/**' | ||
| - 'tests/**' | ||
| - 'scripts/**' | ||
| - 'flows/**' | ||
| - 'docker-compose.yml' | ||
| - 'Dockerfile*' | ||
| - 'Makefile' | ||
| - '.github/workflows/test-e2e.yml' | ||
| - id: decision | ||
| run: | | ||
| if [ "${{ github.event_name }}" = "merge_group" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | ||
| echo "run=true" >> "$GITHUB_OUTPUT" | ||
| elif [ "${{ steps.filter.outputs.relevant }}" = "true" ]; then | ||
| echo "run=true" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "run=false" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| e2e: | ||
| needs: changes | ||
| if: needs.changes.outputs.run == 'true' | ||
| runs-on: | ||
| labels: ["self-hosted", "linux", "ARM64", "langflow-ai-arm64-40gb-ephemeral-sudo"] | ||
| env: | ||
|
|
@@ -99,7 +130,7 @@ jobs: | |
|
|
||
|
|
||
| - name: Run Playwright tests | ||
| working-directory: frontend | ||
| uses: nick-fields/retry@v3 | ||
| env: | ||
| CI: "true" | ||
| OPENSEARCH_HOST: localhost | ||
|
|
@@ -108,7 +139,18 @@ jobs: | |
| OPENSEARCH_PASSWORD: ${{ env.OPENSEARCH_PASSWORD }} | ||
| GOOGLE_OAUTH_CLIENT_ID: "" | ||
| GOOGLE_OAUTH_CLIENT_SECRET: "" | ||
| run: npx playwright test | ||
| with: | ||
| timeout_minutes: 60 | ||
| max_attempts: 2 | ||
| retry_on: error | ||
| command: | | ||
| cd frontend | ||
| npx playwright test | ||
| on_retry_command: | | ||
| # Services are still up — Playwright handles its own fixture | ||
| # lifecycle. Just clear stale artifacts so the retry's report | ||
| # isn't contaminated by the first attempt's output. | ||
| rm -rf frontend/test-results frontend/playwright-report || true | ||
|
|
||
| - name: Collect service logs on failure | ||
| if: failure() | ||
|
|
@@ -150,3 +192,17 @@ jobs: | |
| docker rm -f openrag-backend-proxy 2>/dev/null || true | ||
| make clean || true | ||
| docker system prune -f || true | ||
|
|
||
| required: | ||
|
|
||
| needs: e2e | ||
| if: always() | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Verify e2e result | ||
| run: | | ||
| result="${{ needs.e2e.result }}" | ||
| if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then | ||
| echo "e2e job did not succeed: $result" | ||
| exit 1 | ||
| fi | ||
| echo "e2e result: $result (success or skipped — passing)" | ||
|
Comment on lines
+196
to
+208
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Right now a failed Proposed fix required:
- needs: e2e
+ needs: [changes, e2e]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify e2e result
run: |
- result="${{ needs.e2e.result }}"
- if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then
- echo "e2e job did not succeed: $result"
+ changes_result="${{ needs.changes.result }}"
+ e2e_result="${{ needs.e2e.result }}"
+ if [ "$changes_result" = "failure" ] || [ "$changes_result" = "cancelled" ]; then
+ echo "changes job did not succeed: $changes_result"
+ exit 1
+ fi
+ if [ "$e2e_result" = "failure" ] || [ "$e2e_result" = "cancelled" ]; then
+ echo "e2e job did not succeed: $e2e_result"
exit 1
fi
- echo "e2e result: $result (success or skipped — passing)"
+ echo "changes=$changes_result, e2e=$e2e_result (success or skipped — passing)"🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,14 +2,7 @@ name: Integration Tests | |||||||||
|
|
||||||||||
| on: | ||||||||||
| pull_request: | ||||||||||
| paths: | ||||||||||
| - 'src/**.py' | ||||||||||
| - 'tests/**.py' | ||||||||||
| - 'pyproject.toml' | ||||||||||
| - 'uv.lock' | ||||||||||
| - 'sdks/**' | ||||||||||
| - 'flows/**' | ||||||||||
| - '.github/workflows/test-integration.yml' | ||||||||||
| merge_group: | ||||||||||
| workflow_dispatch: | ||||||||||
| inputs: | ||||||||||
| use_local_images: | ||||||||||
|
|
@@ -18,8 +11,46 @@ on: | |||||||||
| type: boolean | ||||||||||
| default: true | ||||||||||
|
|
||||||||||
| # Serialize E2E and Integration on the same PR/queue ref. They share runner | ||||||||||
| # pool and Docker resources; running them concurrently inflates the flake | ||||||||||
| # rate. Different PRs have different refs and run in parallel as usual. | ||||||||||
| concurrency: | ||||||||||
| group: heavy-tests-${{ github.ref }} | ||||||||||
| cancel-in-progress: false | ||||||||||
|
|
||||||||||
| jobs: | ||||||||||
| changes: | ||||||||||
| runs-on: ubuntu-latest | ||||||||||
| outputs: | ||||||||||
| run: ${{ steps.decision.outputs.run }} | ||||||||||
| steps: | ||||||||||
| - uses: actions/checkout@v4 | ||||||||||
| - uses: dorny/paths-filter@v3 | ||||||||||
|
Comment on lines
+27
to
+28
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
# Show the workflow with line numbers (file should be small enough)
echo "=== test-integration.yml (with line numbers) ==="
nl -ba .github/workflows/test-integration.yml | sed -n '1,200p'
echo "=== Search for action uses across workflows ==="
rg -n "uses:\s*(actions/checkout|dorny/paths-filter|nick-fields/retry)@" .github/workflows || trueRepository: langflow-ai/openrag Length of output: 173 🏁 Script executed: #!/usr/bin/env bash
set -euo pipefail
echo "=== test-integration.yml (with line numbers) ==="
cat -n .github/workflows/test-integration.yml | sed -n '1,200p'
echo "=== Search for action uses across workflows ==="
rg -n "uses:\s*(actions/checkout|dorny/paths-filter|nick-fields/retry)@" .github/workflows || trueRepository: langflow-ai/openrag Length of output: 10086 Pin Current workflow uses mutable tags ( File: .github/workflows/test-integration.yml Proposed hardening patch- - uses: actions/checkout@v4
- - uses: dorny/paths-filter@v3
+ - uses: actions/checkout@<pinned-sha>
+ with:
+ persist-credentials: false
+ - uses: dorny/paths-filter@<pinned-sha>
...
- - name: Run integration tests
- uses: nick-fields/retry@v3
+ - name: Run integration tests
+ uses: nick-fields/retry@<pinned-sha>🧰 Tools🪛 zizmor (1.25.2)[warning] 27-27: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false (artipacked) [error] 27-27: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) [error] 28-28: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy) (unpinned-uses) 🤖 Prompt for AI Agents |
||||||||||
| id: filter | ||||||||||
| if: github.event_name == 'pull_request' | ||||||||||
| with: | ||||||||||
| filters: | | ||||||||||
| relevant: | ||||||||||
| - 'src/**.py' | ||||||||||
| - 'tests/**.py' | ||||||||||
|
Comment on lines
+34
to
+35
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: In picomatch, Citations:
Use recursive Python globs that match nested files.
Proposed fix filters: |
relevant:
- - 'src/**.py'
- - 'tests/**.py'
+ - 'src/**/*.py'
+ - 'tests/**/*.py'
- 'pyproject.toml'
- 'uv.lock'
- 'sdks/**'📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Comment on lines
+34
to
+35
|
||||||||||
| - 'pyproject.toml' | ||||||||||
| - 'uv.lock' | ||||||||||
| - 'sdks/**' | ||||||||||
| - 'flows/**' | ||||||||||
|
|
||||||||||
| - '.github/workflows/test-integration.yml' | ||||||||||
| - id: decision | ||||||||||
| run: | | ||||||||||
| if [ "${{ github.event_name }}" = "merge_group" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | ||||||||||
| echo "run=true" >> "$GITHUB_OUTPUT" | ||||||||||
| elif [ "${{ steps.filter.outputs.relevant }}" = "true" ]; then | ||||||||||
| echo "run=true" >> "$GITHUB_OUTPUT" | ||||||||||
| else | ||||||||||
| echo "run=false" >> "$GITHUB_OUTPUT" | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| tests: | ||||||||||
| needs: changes | ||||||||||
| if: needs.changes.outputs.run == 'true' | ||||||||||
| runs-on: | ||||||||||
| labels: ["self-hosted", "linux", "ARM64", "langflow-ai-arm64-40gb-ephemeral-sudo"] | ||||||||||
| env: | ||||||||||
|
|
@@ -54,7 +85,7 @@ jobs: | |||||||||
|
|
||||||||||
| - name: Checkout | ||||||||||
| uses: actions/checkout@v4 | ||||||||||
|
|
||||||||||
| - name: Verify workspace | ||||||||||
| run: | | ||||||||||
| echo "Current directory: $(pwd)" | ||||||||||
|
|
@@ -78,6 +109,7 @@ jobs: | |||||||||
| run: uv sync | ||||||||||
|
|
||||||||||
| - name: Run integration tests | ||||||||||
| uses: nick-fields/retry@v3 | ||||||||||
| env: | ||||||||||
| OPENSEARCH_HOST: localhost | ||||||||||
| OPENSEARCH_PORT: 9200 | ||||||||||
|
|
@@ -89,16 +121,42 @@ jobs: | |||||||||
| GOOGLE_OAUTH_CLIENT_SECRET: "" | ||||||||||
| # Disable startup ingest noise unless a test enables it | ||||||||||
| DISABLE_STARTUP_INGEST: "true" | ||||||||||
| with: | ||||||||||
| timeout_minutes: 45 | ||||||||||
| max_attempts: 2 | ||||||||||
| retry_on: error | ||||||||||
| command: | | ||||||||||
| # For PRs and merge_group, always build locally since we're | ||||||||||
| # testing new code. For workflow_dispatch, use the input | ||||||||||
| # (defaults to true). | ||||||||||
| USE_LOCAL="${{ inputs.use_local_images }}" | ||||||||||
| if [ "${{ github.event_name }}" != "workflow_dispatch" ] || [ "$USE_LOCAL" != "false" ]; then | ||||||||||
| echo "Running tests with locally built images..." | ||||||||||
| make test-ci-local | ||||||||||
| else | ||||||||||
| echo "Running tests with DockerHub images..." | ||||||||||
| make test-ci | ||||||||||
| fi | ||||||||||
| echo "Keys directory after tests:" | ||||||||||
| ls -la keys/ || echo "No keys directory" | ||||||||||
| on_retry_command: | | ||||||||||
| # Heavyweight reset between attempts — the make target brings | ||||||||||
| # up the full docker-compose stack, and stale containers / | ||||||||||
| # volumes from the first attempt will poison the retry. | ||||||||||
| echo "Integration test attempt failed; tearing down before retry..." | ||||||||||
| docker compose -f docker-compose.yml down -v --remove-orphans || true | ||||||||||
|
|
||||||||||
| docker run --rm -v $(pwd):/work alpine sh -c "rm -rf /work/opensearch-data /work/config /work/langflow-data /work/keys /work/data /work/flows /work/openrag-documents" || true | ||||||||||
|
|
||||||||||
|
|
||||||||||
| required: | ||||||||||
|
|
||||||||||
| needs: tests | ||||||||||
| if: always() | ||||||||||
| runs-on: ubuntu-latest | ||||||||||
| steps: | ||||||||||
| - name: Verify tests result | ||||||||||
| run: | | ||||||||||
| # For PRs, always build locally since we're testing new code | ||||||||||
| # For workflow_dispatch, use the input (defaults to true) | ||||||||||
| USE_LOCAL="${{ inputs.use_local_images }}" | ||||||||||
| if [ "${{ github.event_name }}" == "pull_request" ] || [ "$USE_LOCAL" != "false" ]; then | ||||||||||
| echo "Running tests with locally built images..." | ||||||||||
| make test-ci-local | ||||||||||
| else | ||||||||||
| echo "Running tests with DockerHub images..." | ||||||||||
| make test-ci | ||||||||||
| result="${{ needs.tests.result }}" | ||||||||||
| if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then | ||||||||||
| echo "tests job did not succeed: $result" | ||||||||||
| exit 1 | ||||||||||
| fi | ||||||||||
| echo "Keys directory after tests:" | ||||||||||
| ls -la keys/ || echo "No keys directory" | ||||||||||
| echo "tests result: $result (success or skipped — passing)" | ||||||||||
|
Comment on lines
+150
to
+162
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prevent
Proposed fix required:
- needs: tests
+ needs: [changes, tests]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify tests result
run: |
- result="${{ needs.tests.result }}"
- if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then
- echo "tests job did not succeed: $result"
+ changes_result="${{ needs.changes.result }}"
+ tests_result="${{ needs.tests.result }}"
+ if [ "$changes_result" = "failure" ] || [ "$changes_result" = "cancelled" ]; then
+ echo "changes job did not succeed: $changes_result"
+ exit 1
+ fi
+ if [ "$tests_result" = "failure" ] || [ "$tests_result" = "cancelled" ]; then
+ echo "tests job did not succeed: $tests_result"
exit 1
fi
- echo "tests result: $result (success or skipped — passing)"
+ echo "changes=$changes_result, tests=$tests_result (success or skipped — passing)"🤖 Prompt for AI Agents |
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: langflow-ai/openrag
Length of output: 172
🏁 Script executed:
Repository: langflow-ai/openrag
Length of output: 172
🏁 Script executed:
Repository: langflow-ai/openrag
Length of output: 8349
Harden
.github/workflows/lint-backend.ymlchangesjob actions (pin + disable checkout credential persistence).The
changesjob uses tag-based actions (actions/checkout@v4,dorny/paths-filter@v3) and checkout doesn’t setpersist-credentials, increasing token/credential exposure risk.Proposed hardening patch
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 18-18: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 18-18: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 19-19: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 Prompt for AI Agents