Skip to content

feat(e2e): parallel post-install prep - #2557

Merged
myasnikovdaniil merged 2 commits into
mainfrom
daniil/split-parallel-prep
May 7, 2026
Merged

myasnikovdaniil merged 2 commits into
mainfrom
daniil/split-parallel-prep

Conversation

@myasnikovdaniil

@myasnikovdaniil myasnikovdaniil commented May 2, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

Parallel post-install prep

LINSTOR / StorageClass / MetalLB setup, previously sequential @test cases after the 15 m platform HR wait, now run as a background prep that completes during the platform reconcile. None of them gates platform HR reconcile, so they can move out of the critical path.

New helper hack/e2e-post-install-prep.sh polls for its prerequisites and is awaited at the end of the Install Cozystack test so failures still surface deterministically.

T2-race fix

Wait on the LINSTOR HR being Ready before polling for deploy/linstor-controller. The old 5-min hard timeout fired during cold installs where the LINSTOR HR's dependency chain (cert-manager → piraeus-operator-crds → piraeus-operator → linstor) takes longer than 5 min to resolve.

E2E uses helmReleaseInterval=30s

E2E install passes --set cozystackOperator.helmReleaseInterval=30s to eliminate the 8–10 min Flux dead zone where dependency-blocked HRs are requeued only every 5 min. Operator-side flag and chart value landed in #2509; production defaults are unchanged.

Surfaced from #2500.

Release note

NONE

Summary by CodeRabbit

  • Tests

    • Improved end-to-end test initialization to run concurrent post-install preparation, wait for cluster release reconciliation, verify component readiness, and validate automated storage configuration.
  • Chores

    • Added background post-install setup and logging to increase test reliability and speed up cluster initialization and teardown diagnostics.

@coderabbitai

coderabbitai Bot commented May 2, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8791107c-1687-491c-a676-9f323ebc38f8

📥 Commits

Reviewing files that changed from the base of the PR and between 7ed6444 and d8da80b.

📒 Files selected for processing (1)
  • hack/e2e-post-install-prep.sh

📝 Walkthrough

Walkthrough

The e2e Install Cozystack test now launches a background post-install preparation script while waiting for cluster-wide HelmRelease objects to be reconciled; the test waits for both HelmRelease readiness and the background script, failing if the background script exits non-zero. The new script prepares LINSTOR pools, StorageClasses, and MetalLB resources.

Changes

E2E Test Initialization & Post-Install Preparation

Layer / File(s) Summary
Test Orchestration
hack/e2e-install-cozystack.bats
Launches hack/e2e-post-install-prep.sh in background (logs → /tmp/post-install-prep.log) and records PID; waits for cluster HelmRelease objects and runs kubectl wait --for=condition=ready per release; after HelmRelease reconciliation, waits for post-install process and fails/prints log if it errored. Also sets cozystackOperator.helmReleaseInterval=30s for Helm upgrade.
Prerequisite Waits
hack/e2e-post-install-prep.sh
Waits for LINSTOR HelmRelease to exist and be Ready, waits for linstor-controller Deployment to become Available, and polls until exactly three LINSTOR nodes report Online.
LINSTOR Pool Setup
hack/e2e-post-install-prep.sh
Discovers existing data pools; concurrently creates missing data pools on srv1, srv2, srv3 and waits for all pool-creation tasks to finish.
StorageClasses
hack/e2e-post-install-prep.sh
Applies two StorageClass manifests: local (default, WaitForFirstConsumer, storagePool=data, volume expansion enabled) and replicated (DRBD/replicated options, AutoPlace=3, Immediate binding, volume expansion enabled).
MetalLB Configuration
hack/e2e-post-install-prep.sh
Waits for MetalLB CRDs (ipaddresspools.metallb.io, l2advertisements.metallb.io) and then applies an L2Advertisement and an IPAddressPool (cozystack) with addresses 192.168.123.200-192.168.123.250 (auto-assign).
Observability / Exit
hack/e2e-post-install-prep.sh, hack/e2e-install-cozystack.bats
Script prints [post-install-prep] done on success; BATS prints the captured log and exits non-zero if the background script failed, otherwise prints log and continues tests.

Sequence Diagram

sequenceDiagram
    participant BATS as BATS Test
    participant PostPrep as post-install-prep.sh
    participant Cluster as Kubernetes Cluster
    participant LINSTOR as LINSTOR Cluster
    participant MetalLB as MetalLB

    BATS->>PostPrep: Start in background (stdout → /tmp/post-install-prep.log)
    
    par Parallel Work
        BATS->>Cluster: Wait for HelmRelease objects\nkubectl wait --for=condition=ready (per HelmRelease)
    and
        PostPrep->>Cluster: Wait for LINSTOR HelmRelease Ready
        PostPrep->>Cluster: Wait for linstor-controller Deployment Available
        PostPrep->>LINSTOR: Poll until 3 nodes Online
        PostPrep->>LINSTOR: Create data pools on srv1/srv2/srv3 (concurrent)
        PostPrep->>Cluster: Apply StorageClass manifests (local, replicated)
        PostPrep->>Cluster: Wait for MetalLB CRDs
        PostPrep->>MetalLB: Apply IPAddressPool & L2Advertisement
        PostPrep-->>PostPrep: Print completion message
    end

    BATS->>BATS: HelmRelease reconciliation done
    BATS->>PostPrep: Wait for background PID
    PostPrep-->>BATS: Exit (success or failure)

    alt PostPrep failed
        BATS->>BATS: Print /tmp/post-install-prep.log\nExit non-zero
    else PostPrep succeeded
        BATS->>BATS: Print /tmp/post-install-prep.log\nProceed with test
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hop while tests and upgrades run,
Pools formed by moon and morning sun.
MetalLB hands out addresses fair,
LINSTOR nodes hum in triple care—
Post-install prep: a hoppity done!

🚥 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 'feat(e2e): parallel post-install prep' directly and accurately describes the main change: moving post-install setup into a concurrent/parallel background step that runs during platform reconciliation.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch daniil/split-parallel-prep

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 and usage tips.

@github-actions github-actions Bot added area/platform Issues or PRs related to platform infrastructure (bundle, flux, talos, installer) area/testing Issues or PRs related to testing (e2e, bats, unit tests) kind/feature Categorizes issue or PR as related to a new feature size/L This PR changes 100-499 lines, ignoring generated files labels May 2, 2026
@myasnikovdaniil
myasnikovdaniil marked this pull request as ready for review May 5, 2026 09:36
@dosubot dosubot Bot removed the size/L This PR changes 100-499 lines, ignoring generated files label May 5, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request optimizes the Cozystack installation process by introducing configurable Helm release intervals and parallelizing post-installation tasks. These changes aim to significantly reduce the time required for E2E test suites while improving the reliability of the deployment sequence by addressing known race conditions in the LINSTOR setup.

Highlights

  • Helm Release Interval Configuration: Added support for the cozystackOperator.helmReleaseInterval configuration, allowing for faster reconciliation cycles during E2E testing.
  • Parallel Post-Install Preparation: Refactored LINSTOR and MetalLB setup into a background process to run concurrently with the platform reconciliation, reducing overall installation time.
  • Race Condition Fix: Improved stability by ensuring the LINSTOR HelmRelease is ready before polling for the controller deployment.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@dosubot dosubot Bot added size:L area/ci Issues or PRs related to CI workflows, GitHub Actions, automation do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress labels May 5, 2026

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request optimizes the E2E installation process by moving LINSTOR and MetalLB configuration into a background script, allowing these tasks to run in parallel with the platform reconciliation. It also introduces a configurable Helm release interval for the cozystack-operator, which is set to 30 seconds for E2E tests to accelerate the testing cycle. Feedback is provided regarding the need for explicit PID waiting in the shell script to ensure background process failures are correctly captured, and a recommendation to use the quote function in Helm templates for better value handling.

Comment thread hack/e2e-post-install-prep.sh Outdated
Comment on lines +25 to +31
for node in srv1 srv2 srv3; do
case $created_pools in
*" $node "*) echo " pool 'data' already exists on $node"; continue;;
esac
kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data &
done
wait

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.

medium

In POSIX sh, the wait command without arguments waits for all background processes but always returns a zero exit status, even if some background jobs failed. To ensure the E2E test fails if any of the parallel LINSTOR pool creation commands fail, you should collect the PIDs and wait for each one explicitly. Since set -e is active, the script will exit on the first failed wait.

Suggested change
for node in srv1 srv2 srv3; do
case $created_pools in
*" $node "*) echo " pool 'data' already exists on $node"; continue;;
esac
kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data &
done
wait
pids=""
for node in srv1 srv2 srv3; do
case $created_pools in
*" $node "*) echo " pool 'data' already exists on $node"; continue;;
esac
kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data &
pids="$pids $!"
done
for pid in $pids; do
wait "$pid"
done
References
  1. Handle errors explicitly. Discarding meaningful errors is a bug. (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — fixed in d8da80b. The pool-creation loop now records each background kubectl exec PID into pids, then wait "$pid" runs per job, so a failed pool creation propagates under set -e instead of being masked by the bare wait.

- --disable-telemetry
{{- end }}
{{- if .Values.cozystackOperator.helmReleaseInterval }}
- --helmrelease-interval={{ .Values.cozystackOperator.helmReleaseInterval }}

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.

low

Following Helm best practices and the repository style guide, string values in templates should be quoted to ensure they are correctly parsed as strings, especially when they contain units like 30s.

        - --helmrelease-interval={{ .Values.cozystackOperator.helmReleaseInterval | quote }}
References
  1. Helm template correctness: missing quote (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not applying this one. | quote here would expand inline inside the argument string, rendering - --helmrelease-interval="30s" — i.e. the literal quote characters end up embedded in the arg passed to the operator, and flag.Duration would reject "30s". Quoting is correct on standalone YAML scalars (e.g. value: {{ ... | quote }} further down for KUBERNETES_SERVICE_PORT), but inside --flag=<value> the unquoted form is what we need.

…rallel post-install prep

Two complementary changes that depend on the operator's
`--helmrelease-interval` flag landing via #2509:

1. Installer chart exposes `cozystackOperator.helmReleaseInterval`
   (default empty -> flag not rendered -> operator default 5m
   applies). E2E install passes `30s`. Eliminates the 8-10 min Flux
   dead zone where dependency-blocked HRs (waiting on cert-manager
   webhooks, CRDs) are requeued only every 5 min.

2. LINSTOR / StorageClass / MetalLB setup, previously sequential
   `@test` cases after the 15 m platform HR wait, now run as a
   background prep that completes during the platform reconcile.
   None of them gates platform HR reconcile, so they can move out
   of the critical path. Helper script `hack/e2e-post-install-prep.sh`
   polls for its prerequisites and is awaited at the end of the
   `Install Cozystack` test so failures still surface deterministically.

Includes the T2-race fix: wait on the LINSTOR HR being `Ready`
before polling for `deploy/linstor-controller`. The old 5-min hard
timeout fired during cold installs where the LINSTOR HR's dependency
chain takes longer than 5 min to resolve.

Production defaults are unchanged. The 30 s interval is opt-in per
install command.

Depends on:
- #2509 (operator-side `--helmrelease-interval` flag).

Signed-off-by: Myasnikov Daniil <[email protected]>
Assisted-By: Claude <[email protected]>

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
hack/e2e-post-install-prep.sh (1)

25-31: ⚡ Quick win

wait (no args) silently swallows background-job failures.

In /bin/sh, a bare wait after multiple & jobs always returns 0, so a failed linstor ps cdp on one node will be lost and the StorageClass apply proceeds against an incomplete pool topology. Capture PIDs and wait on each so set -e actually trips.

♻️ Track PIDs and wait per-job
 echo "[post-install-prep] creating LINSTOR storage pools (parallel across nodes)"
 created_pools=$(kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor sp l -s data --pastable | awk '$2 == "data" {printf " " $4} END{printf " "}')
+pids=""
 for node in srv1 srv2 srv3; do
   case $created_pools in
     *" $node "*) echo "  pool 'data' already exists on $node"; continue;;
   esac
-  kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data &
+  kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data &
+  pids="$pids $!"
 done
-wait
+for pid in $pids; do
+  wait "$pid"
+done
🤖 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 `@hack/e2e-post-install-prep.sh` around lines 25 - 31, The bare wait at the end
swallows background failures; change the loop that launches kubectl exec (the
line with "kubectl exec -n cozy-linstor deploy/linstor-controller -- linstor ps
cdp zfs ${node} /dev/vdc --pool-name data --storage-pool data &") to capture
each background PID (e.g., pids+=( $! )) and after the loop iterate over those
PIDs and call "wait <pid>" for each, checking the exit status and exiting
non‑zero if any wait fails so that set -e will trip; reference the loop variable
"node" and the "created_pools" check when making this change.
🤖 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 `@packages/core/installer/templates/cozystack-operator.yaml`:
- Around line 71-73: The template conditionally adds the unknown CLI flag
"--helmrelease-interval" using .Values.cozystackOperator.helmReleaseInterval
which will cause the cozystack-operator to crash because the flag isn't
implemented in cmd/cozystack-operator/main.go for the pinned image (v1.3.0);
remove the conditional block that emits "- --helmrelease-interval={{
.Values.cozystackOperator.helmReleaseInterval }}" from the cozystack-operator
manifest template, or alternatively rebase/update the PR to use an operator
image that includes the new flag implementation before reinstating the
conditional.

---

Nitpick comments:
In `@hack/e2e-post-install-prep.sh`:
- Around line 25-31: The bare wait at the end swallows background failures;
change the loop that launches kubectl exec (the line with "kubectl exec -n
cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc
--pool-name data --storage-pool data &") to capture each background PID (e.g.,
pids+=( $! )) and after the loop iterate over those PIDs and call "wait <pid>"
for each, checking the exit status and exiting non‑zero if any wait fails so
that set -e will trip; reference the loop variable "node" and the
"created_pools" check when making this change.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ca5788af-4514-4786-a047-3293803b78b7

📥 Commits

Reviewing files that changed from the base of the PR and between 5786afe and c86f5d4.

📒 Files selected for processing (4)
  • hack/e2e-install-cozystack.bats
  • hack/e2e-post-install-prep.sh
  • packages/core/installer/templates/cozystack-operator.yaml
  • packages/core/installer/values.yaml

Comment thread packages/core/installer/templates/cozystack-operator.yaml Outdated
@myasnikovdaniil
myasnikovdaniil force-pushed the daniil/split-parallel-prep branch from c86f5d4 to 7ed6444 Compare May 5, 2026 09:46
@github-actions github-actions Bot added size/L This PR changes 100-499 lines, ignoring generated files and removed size:L labels May 5, 2026

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

Actionable comments posted: 1

🤖 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 `@hack/e2e-post-install-prep.sh`:
- Around line 29-31: The background kubectl exec jobs started with "kubectl exec
-n cozy-linstor deploy/linstor-controller -- linstor ps cdp zfs ${node} /dev/vdc
--pool-name data --storage-pool data &" can fail silently because the single
"wait" may report success; change the loop to record each job PID (use $!) into
an array, then loop over those PIDs and run "wait <pid>" for each and test its
exit status, exiting non-zero or failing the script if any wait returns a
non-zero status; ensure you remove the single blind "wait" and replace with
per-PID waits and checks so any failed kubectl exec is propagated.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 02ff9b35-296a-4c41-8455-9424777d9591

📥 Commits

Reviewing files that changed from the base of the PR and between c86f5d4 and 7ed6444.

📒 Files selected for processing (2)
  • hack/e2e-install-cozystack.bats
  • hack/e2e-post-install-prep.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • hack/e2e-install-cozystack.bats

Comment thread hack/e2e-post-install-prep.sh Outdated
@myasnikovdaniil myasnikovdaniil changed the title feat(installer,e2e): cozystackOperator.helmReleaseInterval value + parallel post-install prep feat(e2e): parallel post-install prep May 5, 2026
Address review feedback on hack/e2e-post-install-prep.sh:31:
POSIX `wait` without arguments returns 0 even if a backgrounded
`kubectl exec` failed, which would mask partial LINSTOR prep failures
and let downstream tests run on a half-provisioned cluster. Collect
each background PID and `wait "$pid"` per job so `set -e` exits the
script on the first failed pool creation.

Assisted-By: Claude <[email protected]>
Signed-off-by: Myasnikov Daniil <[email protected]>
@myasnikovdaniil myasnikovdaniil removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress label May 6, 2026

@kvaps Andrei Kvapil (kvaps) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM. Three independent improvements, each well-motivated.

Parallel post-install prep: moving LINSTOR / StorageClass / MetalLB setup into a background helper that completes during the platform reconcile is the right structural fix — none of those gates platform HR reconcile, so they have no business being in the critical path. The hack/e2e-post-install-prep.sh polling for prerequisites and being awaited at the end of "Install Cozystack" preserves deterministic failure surfacing while removing the sequential wait.

T2-race fix: waiting on the LINSTOR HR Ready before polling for deploy/linstor-controller correctly orders the dependency. The previous 5-min hard timeout was racing the cert-manager → piraeus-operator-crds → piraeus-operator → linstor chain on cold installs.

helmReleaseInterval=30s for E2E: pairs cleanly with the operator-side flag from #2509 (already merged). Eliminating the 8-10 min Flux dead zone on dependency-blocked HRs is exactly what makes the parallel prep above actually parallel — without the reduced requeue interval, the prep would still get stuck behind Flux's default 5-min requeue. The operator-default stays 5m, only the e2e harness flips to 30s — right place to apply the knob.

Surfaced from #2500, three load-bearing reductions in cold-run flakiness.

Ship it.

@myasnikovdaniil
myasnikovdaniil merged commit 61de813 into main May 7, 2026
13 of 14 checks passed
@myasnikovdaniil
myasnikovdaniil deleted the daniil/split-parallel-prep branch May 7, 2026 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci Issues or PRs related to CI workflows, GitHub Actions, automation area/platform Issues or PRs related to platform infrastructure (bundle, flux, talos, installer) area/testing Issues or PRs related to testing (e2e, bats, unit tests) kind/feature Categorizes issue or PR as related to a new feature size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants