Skip to content

Scheduled drift detection: weekly full-suite re-run against fresh resolves - #107

Open
AlexanderFengler wants to merge 1 commit into
mainfrom
drift-detection
Open

Scheduled drift detection: weekly full-suite re-run against fresh resolves#107
AlexanderFengler wants to merge 1 commit into
mainfrom
drift-detection

Conversation

@AlexanderFengler

@AlexanderFengler AlexanderFengler commented Aug 6, 2026

Copy link
Copy Markdown
Member

Part of the ecosystem self-healing rollout (aggregation layer: lnccbrown/HSSMSpine#35; siblings: lnccbrown/HSSM#1143, lnccbrown/ssm-simulators#318).

  • new drift.yml: weekly scheduled re-run of the full test workflow via workflow_call against a fresh PyPI resolve of unchanged main — this repo has no push-to-main CI at all, so between PRs nothing else proves main still works
  • failures create/update ONE deduped drift-labeled issue; green runs close it; force_fail dispatch input rehearses the path
  • riding along in run_tests.yml: workflow_call: trigger; setup-uv unpinned from the ancient 0.6.5; the per-PR cache-nuking + --reinstall block removed (every PR cold-downloaded the multi-GB torch/bayesflow/keras/sbi stack), uv caching enabled instead

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added scheduled and manually triggered drift checks.
    • Drift failures now create or update a tracking issue, while successful checks automatically close it.
  • Chores

    • Improved automated test workflow reuse and dependency caching.
    • Simplified test environment setup and package installation.

- weekly re-run of the full test workflow against a fresh dependency
  resolve of unchanged main; this repo has NO push-to-main CI, so
  between PRs nothing else proves main still works
- failures file ONE deduped drift-labeled issue; green runs close it
- run_tests.yml gains workflow_call; setup-uv unpinned from the ancient
  0.6.5; the per-PR cache-nuking block removed (every run cold-
  downloaded the multi-GB torch/bayesflow/keras/sbi stack) with uv
  caching enabled instead
Copilot AI lite review requested due to automatic review settings August 6, 2026 00:50
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Drift monitoring

Layer / File(s) Summary
Reusable test workflow
.github/workflows/run_tests.yml
The test workflow now supports workflow_call. uv setup enables caching, removes manual cache handling, and uses uv sync --all-groups.
Drift execution and issue reporting
.github/workflows/drift.yml
A scheduled and manually dispatchable workflow runs tests, supports forced failures, and closes, updates, or creates a deduplicated drift issue based on results.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Trigger as Schedule or manual dispatch
  participant Drift as Drift workflow
  participant Tests as Reusable test workflow
  participant Issues as GitHub Issues
  Trigger->>Drift: Start workflow with optional force_fail
  Drift->>Tests: Run reusable test workflow
  Tests-->>Drift: Return test result
  Drift->>Issues: Close, update, or create drift issue
Loading

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: scheduled weekly drift detection through full-suite reruns against fresh dependency resolutions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch drift-detection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI 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.

Pull request overview

Adds scheduled “drift detection” to continuously validate main against fresh dependency resolves by reusing the existing test workflow, and improves CI performance by enabling uv caching and removing the prior cache-nuking/reinstall behavior.

Changes:

  • Add a new scheduled/manual drift.yml workflow that runs the full test suite and creates/updates/closes a single deduped drift-labeled issue based on results.
  • Make run_tests.yml reusable via workflow_call so it can be invoked by drift.yml.
  • Update run_tests.yml to use setup-uv with caching enabled and remove the cache-clearing + uv sync --reinstall behavior.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
.github/workflows/run_tests.yml Adds workflow_call trigger and enables uv caching / removes forced reinstall for the main test job.
.github/workflows/drift.yml New scheduled workflow that calls the test workflow and manages a deduped drift-tracking issue.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +23 to +25
tests:
uses: ./.github/workflows/run_tests.yml

Comment on lines 28 to +33
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
version: "0.6.5"
# enable-cache: true
# cache-dependency-glob: "pyproject.toml pdm.lock"

- name: Clear all caches
run: |
rm -rf ~/.cache/pip
rm -rf ~/.cache/uv
rm -rf ~/.cache/conda
rm -rf ~/.cache/npm

version: "latest"
enable-cache: true
cache-dependency-glob: "pyproject.toml"

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/drift.yml:
- Around line 42-59: Update the FAILED_JOBS decision logic in the drift workflow
so an existing issue is closed only when RESULT_TESTS equals success. Treat
cancelled, skipped, and any other non-success test results as inconclusive by
keeping the issue open, while preserving the existing force-fail handling.
- Around line 26-31: Add a job-level concurrency group to the report job in
drift.yml, with cancel-in-progress set to false, so overlapping scheduled or
manual runs serialize the issue list-and-create sequence used by the report
steps.
- Around line 23-24: Update the drift workflow’s tests and reporting jobs so
they only execute when the workflow ref is the repository’s default branch,
including manually dispatched runs with a supplied ref. Apply the same
default-branch condition to the job that uses needs.tests.result for shared
drift issue updates, while preserving the existing test and reporting behavior
on the default branch.
- Around line 18-20: Restrict the issues: write permission to the report job in
the workflow, and remove it from the top-level permissions inherited by the
reusable tests job. Keep contents: read at the appropriate shared scope and
ensure report retains issues: write.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b6a9efdc-aa3b-4c12-9ce9-1ca446901527

📥 Commits

Reviewing files that changed from the base of the PR and between d725ae3 and 045d6cb.

📒 Files selected for processing (2)
  • .github/workflows/drift.yml
  • .github/workflows/run_tests.yml

Comment on lines +18 to +20
permissions:
contents: read
issues: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow files =="
git ls-files .github/workflows || true

echo
echo "== drift.yml =="
cat -n .github/workflows/drift.yml 2>/dev/null || true

echo
echo "== run_tests.yml relevant permissions/usages =="
if [ -f .github/workflows/run_tests.yml ]; then
  wc -l .github/workflows/run_tests.yml
  rg -n "permissions:|permissions \{|uses:|actions/checkout|pypi|pip|github_token|GITHUB_TOKEN|persist-credentials" .github/workflows/run_tests.yml -C 3
fi

echo
echo "== all workflow permissions =="
python3 - <<'PY'
from pathlib import Path
import re
for p in sorted(Path('.github/workflows').glob('*.yml')) + sorted(Path('.github/workflows').glob('*.yaml')):
    txt=p.read_text()
    lines=[]
    for i,line in enumerate(txt.splitlines(),1):
        if re.search(r'^\s*(permissions|uses):\s*(.*?)$', line):
            lines.append((i,line.strip()))
    if lines:
        print(f"\n--- {p} ---")
        for i,l in lines[:40]:
            print(f"{i}: {l}")
PY

Repository: lnccbrown/LANfactory

Length of output: 5205


🌐 Web query:

GitHub Actions reusable workflows inherited permissions write scope

💡 Result:

When using GitHub Actions reusable workflows, the called workflow inherits permissions from the calling (caller) workflow [1][2]. Because these permissions flow from the caller, you must manage them at the caller's level to ensure the reusable workflow has the necessary write access [3][4]. Key principles regarding inherited permissions include: Permissions Flow: A reusable workflow inherits the GITHUB_TOKEN permissions defined in the caller workflow [1][5]. If no specific permissions are defined in the caller's job, the workflow uses the repository's default GITHUB_TOKEN permissions [5][6]. Downgrading Only: Permissions can only be maintained or downgraded (made more restrictive) by a called workflow [5][6]. A called workflow cannot elevate or expand permissions beyond what the caller has granted [5][4]. For example, if a caller workflow grants only read access, the reusable workflow cannot escalate this to write access [5]. Requirement for Top-Level Declaration: To ensure your reusable workflow receives the correct write scopes, you must declare the permissions at the workflow level (the top-level permissions key) in the caller workflow [3]. While you can define permissions at the job level in standard workflows, job-level permissions are often ignored or behave inconsistently when calling reusable workflows; therefore, setting them globally for the caller workflow is the recommended practice to avoid 403 Forbidden errors [3]. OIDC Tokens: If your reusable workflow requires an OIDC token (e.g., for cloud authentication), you must explicitly set id-token: write in the caller's permissions block [7]. Explicit Configuration: Although reusable workflows inherit permissions automatically, it is considered a best practice to explicitly declare permissions in the reusable workflow itself (e.g., permissions: {}) [2]. This helps satisfy security scanners (like CodeQL), clarifies the workflow's requirements, and ensures that even if a caller is overly permissive, the reusable workflow remains limited to its actual needs [2].

Citations:


🌐 Web query:

GitHub Actions job-level permissions reusable workflow permissions inherit

💡 Result:

In GitHub Actions, reusable workflows inherit the GITHUB_TOKEN permissions defined by the calling workflow [1][2]. Key points regarding this inheritance: 1. Inheritance and Down-scaling: The reusable workflow receives the permissions granted by the caller, but these permissions can only be maintained or downgraded (made more restrictive) by the reusable workflow [3][1]. They cannot be elevated [1][4]. 2. Default Behavior: If no permissions are explicitly specified in the calling job (or at the top level of the caller workflow), the reusable workflow will operate with the default GITHUB_TOKEN permissions configured for the repository [3][1]. 3. Configuration Conflict: You cannot use the jobs.<job_id>.permissions key in the same job that calls a reusable workflow via jobs.<job_id>.uses [5]. If you define permissions on a job that calls a reusable workflow, it will cause a configuration error [5]. 4. Recommended Approach: To control permissions for a job calling a reusable workflow, you should define the permissions block at the top level of the calling workflow file [5]. This ensures the permissions are clearly established before the job is executed, avoiding the conflict between the permissions and uses keys [5]. It is considered a security best practice to explicitly define minimal permissions at the top level of all your workflows (including reusable ones) to avoid relying on implicit defaults, which may vary depending on repository and organization settings [6][7][2].

Citations:


🌐 Web query:

GitHub Issues permission GITHUB_TOKEN create_issues write actions/checkout persist-credentials false

💡 Result:

To create GitHub issues using the GITHUB_TOKEN in a GitHub Actions workflow, you must explicitly grant the issues: write permission within your workflow file [1][2][3][4]. By default, workflows may have restricted permissions, and failing to declare the necessary scope will result in a "Resource not accessible by integration" or "missing required scope" error [3][4]. You can configure these permissions at the workflow or job level using the permissions key [5][1]. For example: permissions: issues: write Regarding your mention of actions/checkout with persist-credentials: false, these are separate concerns [6][7]. The actions/checkout action uses the persist-credentials input (which defaults to true) to determine whether the GITHUB_TOKEN (or a configured PAT/SSH key) is persisted into the local Git configuration [6][7]. Setting persist-credentials: false prevents the token from being saved to the local git config, which is a security best practice when you do not need to perform authenticated Git commands (like pushing code) from within your steps [6][8]. If you are using actions/checkout only to fetch code, persist-credentials: false is recommended to reduce security risk [6][8]. This choice does not negatively impact your ability to use the GITHUB_TOKEN for other API tasks, such as creating issues, provided that the required API permissions (issues: write) are correctly defined in your workflow [1][3]. Summary of Key Points: - Explicit Permissions: Use permissions: { issues: write } in your YAML to allow issue creation [1][2]. - persist-credentials: Setting persist-credentials: false in actions/checkout is a security practice that prevents your token from being stored in the local Git config; it does not block the token's use for GitHub API requests [6][9]. - Integration: Both settings are standard practices for securing workflows while enabling necessary automation [5][6].

Citations:


Security Misconfiguration (CWE-250)

Reachability: External

Scope issues: write to report.

The reusable tests job inherits the caller’s issues: write permission while resolving fresh dependencies and running tests. persist-credentials: false only prevents checkout credentials from being persisted locally and does not reduce the job token’s issue write scope.

Proposed permission scope
 permissions:
   contents: read
-  issues: write

 jobs:
   tests:
+    permissions:
+      contents: read
     uses: ./.github/workflows/run_tests.yml

   report:
+    permissions:
+      contents: read
+      issues: write
🧰 Tools
🪛 zizmor (1.29.0)

[error] 20-20: overly broad permissions (excessive-permissions): issues: write is overly broad at the workflow level

(excessive-permissions)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/drift.yml around lines 18 - 20, Restrict the issues: write
permission to the report job in the workflow, and remove it from the top-level
permissions inherited by the reusable tests job. Keep contents: read at the
appropriate shared scope and ensure report retains issues: write.

Source: Linters/SAST tools

Comment on lines +23 to +24
tests:
uses: ./.github/workflows/run_tests.yml

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files .github/workflows || true

echo "== drift workflow =="
sed -n '1,220p' .github/workflows/drift.yml 2>/dev/null || true

echo "== tests workflow outline =="
if [ -f .github/workflows/run_tests.yml ]; then
  wc -l .github/workflows/run_tests.yml
  ast-grep outline .github/workflows/run_tests.yml --view expanded || true
  sed -n '1,260p' .github/workflows/run_tests.yml
fi

echo "== references to issue/drift/main/reusable workflow =="
rg -n "issue|drift|main|workflow_dispatch|uses: \./\.github/workflows/run_tests|needs:|result|close|open|gh" .github/workflows/. 2>/dev/null || true

Repository: lnccbrown/LANfactory

Length of output: 8701


🌐 Web query:

GitHub reusable workflows github.ref default branch input ref workflow_dispatch workflow_call

💡 Result:

In GitHub Actions, the github.ref context and the calling mechanism for reusable workflows have specific behaviors you should be aware of regarding branches, workflow dispatch, and workflow calls. ### Using References in Reusable Workflows You cannot use expressions or context variables (like ${{ github.ref }} or ${{ github.sha }}) inside the uses keyword when calling a reusable workflow [1][2][3]. GitHub Actions requires a static reference—a branch name, tag, or commit SHA—to parse the workflow file at execution time [2][3]. * Same Repository: If your reusable workflow is in the same repository, you should omit the @{ref} suffix entirely (e.g., uses: ./.github/workflows/my-workflow.yml) [1][2][3]. When you omit this, GitHub automatically executes the workflow version from the same commit as the caller workflow [1][2]. * External Repositories: If calling a workflow from another repository, you must hardcode the version (e.g., uses: octo-org/repo/.github/workflows/my-workflow.yml@v1) [1][3]. ### The github Context in Reusable Workflows When a reusable workflow is triggered, the github context (including github.ref) is associated with the caller workflow, not the called reusable workflow [4][5]. This means the reusable workflow does not inherently "know" which specific branch or tag was used to call it if it was referenced by a tag or branch name [5]. If your reusable workflow needs to act on a specific branch or tag (e.g., for actions/checkout), you must explicitly pass that reference as an input [5][3]: 1. Define an input in the reusable workflow's on.workflow_call.inputs section [6][4]. 2. Pass the value from the caller using ${{ github.ref }} or ${{ github.ref_name }} inside the jobs.<job_id>.with block [4][5]. ### Workflow Dispatch vs. Workflow Call * Workflow Dispatch: The workflow_dispatch event allows you to trigger a workflow manually [6][7]. It is distinct from workflow_call (reusable workflows) and only receives events when the workflow file exists on the default branch [6]. * Inputs: While both workflow_dispatch and workflow_call support inputs, they serve different purposes [6][4]. workflow_call allows one workflow to use another as a component, whereas workflow_dispatch is typically used for on-demand execution [6][7]. Remember that the inputs context inside a reusable workflow is populated only by the values defined in its own on.workflow_call configuration [4][8]. Attempting to access inputs in the caller workflow's job-level if conditions will fail, as those inputs exist only within the scope of the called workflow [8].

Citations:


🌐 Web query:

site:docs.github.com GitHub Actions reusable workflows workflow_dispatch branch workflow_call ref input github.ref default branch

💡 Result:

GitHub Actions utilizes specific mechanisms for triggering, referencing, and passing data to workflows, with distinct behaviors for reusable and manually dispatched workflows. 1. Reusable Workflows (workflow_call) Reusable workflows are defined using the workflow_call trigger [1][2]. They can be called from another workflow (the caller) by referencing their file path and a specific version (ref) [1][3]. - Referencing: You can reference a reusable workflow using the syntax {owner}/{repo}/.github/workflows/{filename}@{ref} [1][4]. The {ref} can be a branch name, a release tag, or a commit SHA [4][5]. - Context and Inputs: When a reusable workflow is triggered, the github context is associated with the caller workflow, not the called workflow [5][6]. Inputs are defined in the called workflow under on.workflow_call.inputs [2] and passed from the caller workflow using the with keyword in a job [1][2]. - Repository Context: Actions within a reusable workflow run as if they were part of the caller workflow; for example, actions/checkout will check out the caller repository's code, not the reusable workflow's repository [3]. 2. Manually Triggered Workflows (workflow_dispatch) The workflow_dispatch trigger allows workflows to be run manually [7]. - Default Branch Requirement: Traditionally, for a workflow to be triggered via workflow_dispatch, the workflow file must exist on the repository's default branch [8][7]. - Branch Execution: While the file must reside on the default branch to be visible and available for manual triggering, you can execute the workflow on a different branch by specifying the ref (e.g., using the --ref flag in the GitHub CLI: gh workflow run WORKFLOW --ref BRANCH) [7]. - Inputs: Inputs for workflow_dispatch are defined in the workflow file and accessed within the workflow via the inputs context or github.event.inputs [8][2][9]. 3. Key Considerations for github.ref - github.ref: This context variable represents the fully-formed ref (e.g., refs/heads/<branch_name> or refs/tags/<tag_name>) of the branch or tag that triggered the workflow [10]. In the context of reusable workflows, because the github context is inherited from the caller [5][6], github.ref will point to the branch or tag of the caller repository that initiated the run, not the branch of the repository hosting the reusable workflow [10].

Citations:


Restrict drift reporting to the default branch.

workflow_dispatch can run this call from a non-default branch when a ref is supplied. The tests job then runs that branch, but report: always() uses needs.tests.result to create or close the shared drift issue, so a passing branch can close an open issue and a failing branch can create a false drift issue. Drive both jobs from the default branch before using the result for issue updates.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/drift.yml around lines 23 - 24, Update the drift
workflow’s tests and reporting jobs so they only execute when the workflow ref
is the repository’s default branch, including manually dispatched runs with a
supplied ref. Apply the same default-branch condition to the job that uses
needs.tests.result for shared drift issue updates, while preserving the existing
test and reporting behavior on the default branch.

Comment on lines +26 to +31
report:
needs: [tests]
if: always()
runs-on: ubuntu-latest
steps:
- name: Create, update, or close the deduped drift issue

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Serialize the issue update job.

Two overlapping scheduled or manual runs can both find no open issue at Lines 50-52 and both create one. Add job-level concurrency with cancel-in-progress: false so the list-and-create sequence is serialized.

Proposed concurrency guard
   report:
+    concurrency:
+      group: drift-issue-reporter
+      cancel-in-progress: false
     needs: [tests]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
report:
needs: [tests]
if: always()
runs-on: ubuntu-latest
steps:
- name: Create, update, or close the deduped drift issue
report:
concurrency:
group: drift-issue-reporter
cancel-in-progress: false
needs: [tests]
if: always()
runs-on: ubuntu-latest
steps:
- name: Create, update, or close the deduped drift issue
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/drift.yml around lines 26 - 31, Add a job-level
concurrency group to the report job in drift.yml, with cancel-in-progress set to
false, so overlapping scheduled or manual runs serialize the issue
list-and-create sequence used by the report steps.

Comment on lines +42 to +59
FAILED_JOBS=""
if [ "$RESULT_TESTS" = "failure" ]; then
FAILED_JOBS=" tests"
fi
if [ "$FORCE_FAIL" = "true" ]; then
FAILED_JOBS="$FAILED_JOBS (force_fail rehearsal)"
fi

EXISTING=$(gh issue list --repo "$GITHUB_REPOSITORY" --label drift \
--state open --search "in:body \"$KEY\"" \
--json number --jq '.[0].number // empty')

if [ -z "$FAILED_JOBS" ]; then
if [ -n "$EXISTING" ]; then
gh issue close "$EXISTING" --repo "$GITHUB_REPOSITORY" \
--comment "Scheduled drift checks green again: $RUN_URL"
fi
exit 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not treat cancelled or skipped tests as green.

FAILED_JOBS remains empty when needs.tests.result is cancelled or skipped. The workflow then closes an existing drift issue as green without a successful test run. Close the issue only when RESULT_TESTS is success. Preserve the issue for all inconclusive results.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/drift.yml around lines 42 - 59, Update the FAILED_JOBS
decision logic in the drift workflow so an existing issue is closed only when
RESULT_TESTS equals success. Treat cancelled, skipped, and any other non-success
test results as inconclusive by keeping the issue open, while preserving the
existing force-fail handling.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants