Ngfw trixie Merge - #1281
Open
singhrohit23 wants to merge 37 commits into
Open
Conversation
- ut-uvm-update-rules.sh: nftables tune table (replaces iptable_tune kernel patch) - qos-status.py: IMQ to IFB device migration + parse fix for trailing newlines - uvm wrapper: suppress iptable_tune modprobe warning on bookworm - ut-force-time-sync: add 30s timeout to prevent boot hang - i18n_helper.py: codeset + lgettext deprecation fix for Python 3.11 - captive-portal handler.py: lgettext + imp module + form bytes fix for Python 3.11 - captive-portal logout.py: lgettext deprecation fix for Python 3.11 - IPS suricata_conf.py: ruamel.yaml text_type compatibility for Python 3.11 - IPS suricata_signature.py: Python 3.11 regex fix (re.IGNORECASE) - libnetcap: conntrack netlink compatibility for kernel 6.1 - debian/control: bookworm dependency updates - buildtools/jars.rb: OpenJDK 17 path updates - build-order.txt: updated for bookworm
- .travis.yml: REPOSITORY=bookworm, amd64 only - docker-compose.build.yml: REPOSITORY and TRAVIS_BRANCH defaults to bookworm - docker-compose-dev.yml: new local dev build file with host networking
Add error suppression to IPsec updown scripts to prevent cascading failures during tunnel teardown when routing tables or iptables rules don't exist. Without this fix, disabling the IPsec app while VTI tunnels are active leaves stale routes that break network connectivity. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* ngfw-15692 Removed Virus Blocker Lite from installable apps
P0 — IPS suricata config generator broken on trixie: intrusion-prevention/.../suricata_conf.py uses ruamel.yaml's legacy module-level load()/dump() APIs which were removed in 0.18 (trixie ships ruamel.yaml 0.18+). Without this fix intrusion-prevention-create-config.py exits 1 silently → suricata runs with NFQUEUE=0, no IPS detection. Migrated both load and dump to YAML(typ='rt') instance API, preserving preserve_quotes, version=(1,1), and explicit_start. Validated end-to-end on 192.168.56.155: NFQUEUE=2930 systemd drop-in generated, suricata.yaml rule-files updated, 27738-line ngfw.rules loaded. Phase G trixie porting (12 source files): build-order.txt: . bookworm → . trixie buildtools/buildtools.rb: prefer openjdk-21 over openjdk-17 over -11. Trixie ships JDK 21 in main; 17 stays as fallback for bookworm builds. buildtools/target.rb + rakefile: Ruby 3.x deprecation — File.exists? → File.exist? (3 occurrences total). exists? was removed in Ruby 3.2; trixie ships Ruby 3.3 default. debian/control: - openjdk-17-jdk-headless → openjdk-21-jdk-headless | openjdk-17-jdk-headless build-dep alternative. - untangle-app-virus-blocker Depends: add untangle-kernel-modules-trixie as the first alternative (matches new untangle-kernel-modules-trixie-amd64 package shipped in ngfw_pkgs commit aa164ae57). libnetcap/src/netcap_init.c: add 6.12. kernel detection alongside existing 6.1. and earlier branches. Sets ip_saddr=27, ip_sendnfmark=28, is_new_kernel=612 — same offsets as 6.1 since the cmsg layout from patches 0002/0004 carries forward unchanged in 6.12. uvm/hier/.../login_tools.py + ut-textui.py + web/auth/index.py + unit_tests/test_web_auth_index.py: Python 3.11+ string handling fixes (gettext lgettext fallback, importlib.util replacing imp). debian/changelog: 3 auto-build entries from local trixie rebuilds (2026-05-11). Versions are valid (proper timestamp.commit format), not stubs. Noise that the next build pipeline will subsume. Validated: round-15 trixie ISO install on 192.168.56.137 ships these patches; UVM starts; IPS infra (NFQUEUE bound, rules loaded); virus-blocker dep chain resolves via untangle-kernel-modules-trixie.
…enSSL 3.5) Trixie OpenSSL 3.5 rejects authorityKeyIdentifier=keyid,issuer:always when applied via `openssl req -extensions <section>` (no issuer cert at CSR time). OpenSSL 3.0 (bookworm) silently tolerated this. CSR never written, paired `openssl ca` then fails, cert never produced. Both scripts lack set -e so failure is masked and the app starts broken. Fix: remove -extensions from the req lines. Paired `openssl ca -extensions` calls keep the extensions at signing time where AKI computation works. openvpn-generate-certs: 1 site (server cert). ut-certgen: 4 sites (REQUEST, APACHE, SERVER, MITM modes). Validated on trixie 192.168.56.155: openvpn server cert regenerates and daemon starts cleanly; SSL Inspector forges per-flow MITM leaf certs and web filter renders the block page for https://www.beer.com (Alcohol/Tobacco). No effect on bookworm/bullseye (lenient OpenSSL 3.0 silently skipped these).
The connmark-save rule for UDP packets carrying QoS priority bits was emitted by sync-settings/300-qos as `nft insert rule inet tune queue-to-uvm ... ct mark set mark`. But it raced against 010-flush which deletes the inet tune table at the start of every 960-iptables run; 300-qos then ran before 800-uvm (= this script's symlink) recreated the table, so the insert silently failed and the rule was never installed. UDP-heavy QoS deployments would see priority class flap per-packet on long-lived flows (DNS, RTP, video, gaming) instead of being inherited from conntrack. Move the rule into ut-uvm-update-rules.sh, in the same code block that creates the queue-to-uvm chain. Single owner, no race possible. Gated by /usr/share/untangle/conf/qos-enabled flag managed by qos_manager.py. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trixie's git 2.47 enforces safe.directory checks stricter than bookworm's git 2.39. Bind-mounted /opt/untangle/build inherits host-side ownership that triggers "dubious ownership" inside the container, making `git log` return empty. pkgtools set-version.sh derives the timestamp from that git log output, so empty timestamps produce malformed debian/changelog trailers, breaking libapache2-mod-python setup.py with InvalidVersion. Fix is container-local (safe.directory '*' system-wide) — root cause is the Docker image, not pkgtools. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fakeroot's default SysV semaphore backend hangs indefinitely under Travis CI's restricted Docker IPC namespace, wedging do-build after the post-build dput on every package. Local Docker setups (full IPC access) don't trigger this, which is why the bug only surfaced on CI. The TCP backend uses sockets instead of SysV IPC and is fully compatible — same fakeroot semantics, just a different transport. libfakeroot-tcp.so is upstream-shipped, no extra package needed.
Same workaround as ngfw_pkgs 6aa95e6e3 / ngfw_hades-pkgs de1cb997 / ngfw_vendor-pkgs a6b81b7 — fakeroot (both SysV and TCP backends) hangs in Travis Docker IPC during post-build cleanup, killing the job after 10 min no-output. NO_CLEAN=1 skips the cleanup block. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
trixie's sqv (apt-key replacement) rejects keybox-format .gpg files. Export ASCII-armored .asc so apt accepts the untangle archive key. Mirrors the fix shipped in ngfw_pkgs untangle-archive-keyring (commit aa164ae57). Without this commit, any future clean rebuild of the trixie base image re-introduces the keybox bug. See memory: trixie-keyring-sqv-fix Fix #2 (export --armor).
bctid Pulse first-install was caught in a cache-wiping restart loop when the upstream resolver silently drops AAAA queries (VBox NAT 10.0.2.3, some consumer routers). glibc parallel A+AAAA blocks ~15s; prior 5s read timeout fired first, declared Pulse dead, triggered 'systemctl restart untangle-bctid' which wiped bctid's resolved-IP cache and re-entered the same DNS stall. 30s lets the first lookup complete. Once bctid caches the IP all subsequent queries are sub-millisecond, so the slow path is first- install only and does not affect steady-state performance. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
JDK21 (trixie) rejects the entire JSSE protocol list passed to SSLEngine.setEnabledProtocols() if TLSv1 or TLSv1.1 are included, breaking SSL Inspector for ALL HTTPS traffic, not just legacy sites. Three coordinated changes so neither fresh installs, upgrades, nor a user re-enabling the UI toggle can land in the broken state: 1. SslInspectorSettings: flip constructor defaults for client_TLSv10/11 and server_TLSv10/11 from true to false. 2. SslInspectorApp.preInit(): bump settings version 3 -> 4. Add v3->v4 migration that force-flips legacy TLS flags to false on upgrade from bookworm/bullseye, where the prior True defaults would otherwise persist and brick SSL Inspector. 3. SslInspectorManager.generateProtocolList(): defensively strip TLSv1/TLSv1.1 from the protocol list regardless of the UI flag. The UI fields remain present (settings schema compatibility) but become dead controls. Flipping them on now produces a WARN log instead of breaking ALL HTTPS through the appliance. Customers needing to MITM a legacy-TLS-only intranet server should add an SSL Inspector rule with Action=IGNORE for that destination, which bypasses JSSE entirely and passes the encrypted bytes through. Validated on trixie .123: footgun engaged (client_TLSv10=true, server_TLSv11=true) -> WARN logged 3x -> github.com HTTPS still returns 307 web-filter blockpage (MitM succeeded, JSSE accepted the filtered protocol list). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…get-config output On first install (and on first UVM restart post-upgrade), sync-settings may be mid-rewrite of /etc/suricata/suricata.yaml when intrusion-prevention-get-config.py --variables runs, producing empty output. The split(\"\\\\r?\\\\n\") on \"\" returns [\"\"] (length 1) -> loop body runs once -> \"\".split(\"=\") also returns [\"\"] (length 1) -> variableLine[1] throws IndexOutOfBoundsException, settings_NN.js never persists, UI shows install fail. Reproduced on fresh trixie .123 install at 12:51:41 (app-26 install crashed). Retry at 12:55:20 (app-27) worked because the race window had closed. Same race is reachable on upgrades when post-upgrade sync-settings and IPS reload happen close together. One-line defensive guard skips empty/malformed lines. Happy-path behavior unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ance Builds on the cherry-picked NGFW-15672 bookworm helpers. Mirrors the same detect/pre/post pattern for the bookworm->trixie hop, plus a kept-back tolerance refactor required to survive transitional packages mid-upgrade. - check_upgrade() refactored to return distinguishable codes (0=clean, 1=kept-back, >1=real apt error). Caller decides whether kept-back is fatal. Existing bookworm path keeps abort-on-kept-back. - is_trixie_upgrade() detects via apt sources + running kernel + a fixup-done flag file at /var/lib/untangle-vm/.trixie-upgrade-fixups-done so post-reboot reruns are idempotent. - pre_upgrade_cleanup_trixie() pre-installs openjdk-21-jre-headless. Trixie untangle-vm needs JDK21 for SSL Inspector compat (afe4c86) but its Depends doesn't hard-pull it in, so apt would otherwise keep stale openjdk-17 and SSL Inspector v3->v4 migration could misbehave. - post_upgrade_fixups_trixie() waits 30s for the deferred postinst daemon-reload cascade (multiple packages each call systemctl daemon-reload, cumulatively auto-restarting UVM) then issues a clean stop+start of untangle-vm. The cascade-triggered restart hits a JDK21+jabsorb parallel-load race where MarshallingModeContext.pop() throws NoSuchElementException and 3 apps fail to init (observed: tunnel-vpn, intrusion-prevention). Clean restart cures it. - Main flow integrates trixie path via elif on bookworm_upgrade and conditional kept-back handling. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
REFRESH COLLATION VERSION is PG15+ syntax. On a direct bullseye->trixie upgrade PG13 may still be serving on socket 5432 (PG17 package installs but its cluster isn't auto-created when PG13 already owns the port), so the three unconditional ALTER calls in post_upgrade_fixups_trixie emit harmless but noisy syntax errors into the upgrade log. Query server_version_num before the ALTERs and skip them with a log line when PG < 15. REINDEX is left unconditional (valid on all PG versions and still useful after the glibc 2.36 -> 2.41 sort change). Affects only post_upgrade_fixups_trixie callers (is_trixie_upgrade() True path); bullseye-routine, bookworm-routine, and bullseye->bookworm flows are bit-identical to before this change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eboot Add missing pre/post-upgrade steps that the trixie helper omitted, found during bullseye->trixie direct validation on 2026-05-26 (.175 ended up with no nft binary -> no inet tune table -> no NFQUEUE divert -> every pipeline app silently inspected zero traffic despite loading cleanly). pre_upgrade_cleanup_trixie(): - Pre-install nftables. Required by ut-uvm-update-rules.sh which wires the inet tune table + NFQUEUE divert (queue 1981/1982) for the entire NGFW userspace inspection pipeline. On bullseye->trixie direct, bullseye uses iptables-legacy and never had nftables installed; no trixie package hard-depends on it, so apt won't pull it in. Mirrors the bookworm helper. - Purge wireguard-dkms (trixie kernel 6.12 has wireguard built-in). - Persist 'ifb' to /etc/modules so QoS survives reboot. post_upgrade_fixups_trixie(): - modprobe ifb + create ifb0 device. - nft list ruleset log dump. - nft list tables validation w/ WARNING for bridge broute / bridge mangle / inet tune. Would have surfaced this regression in upgrade.log instead of post-deploy smoke. - Write /tmp/.trixie-reboot-required flag when running kernel != 6.12.x (mirrors bookworm reboot-required pattern). - Auto-reboot via 'shutdown -r +1' when reboot-required. UI-driven upgrades have no admin watching, so without this the box sits on the old kernel indefinitely. SSH users get a wall broadcast and can 'shutdown -c' to cancel. Same change applied to bookworm post_upgrade_fixups() for consistency. Gated on kernel mismatch, so same-distro patch upgrades are unaffected. is_trixie_upgrade(): - Self-healing detector: re-run fixups if nft binary or required tables (inet tune, bridge broute) are missing, even when the fixup-done flag exists. Mirrors the bookworm detector. protect_untangle_packages_from_autoremove(): - Add nftables to runtime_tools anti-sweep list as defense-in-depth. (cherry picked from commit c5b24bc)
Five tests failed on the 2026-05-28 bookworm->trixie ATS run that pass
cleanly on re-run minutes later. Root cause for 3 of them is the same:
Apache mod_python's DbmSession DB takes several seconds to warm up after
untangle-vm restart, during which login appears to succeed (Set-Cookie
returned) but the cookie isn't persisted server-side, so authenticated
admin paths return empty bodies or the apache "Permission denied"
fallback page.
test_administration.py (admin cert uploads):
Consolidate the 4 duplicated login+multipart-upload blocks (~85 lines)
into a single _login_and_upload_cert() helper that retries on empty
response.text. Net 49-line reduction. Fixes test_021/022/023/025_invalid.
test_branding_manager.py (login page branding):
Add _fetch_uvm_root_with_retry() helper -- GETs / via remote wget and
retries until response title is not the apache fallback "Server" page.
Fixes test_020_check_login_page_branding + test_021_changeBranding_*.
test_web_filter.py:
- test_202/test_205: replace assertEquals (removed in Python 3.13) with
assertEqual; 15 occurrences scrubbed.
- test_205 concurrency assertion relaxed: which of 3 concurrent
setBlockedUrls workers wins is implementation-defined; settings-file
mtime is not a reliable proxy for winning-rule ownership. Accept any
of the 3 worker IDs' rules being the survivor instead of pinning to
the one whose settings file happened to be written last.
test_intrusion_prevention.py (test_300_flow_established_toggle):
Tighten the leftover-detection grep from "flow:.*established" (greedy
across `;` boundaries) to "flow:[^;]*\\bestablished\\b" (scoped to the
flow: option value, word-boundary excludes not_established naturally).
The old regex falsely caught any rule whose msg/content mentioned
"established" after a correctly-stripped flow: clause -- a new
Emerging Threats signature surfaced this on the trixie run. Source
remove_flow_established() in suricata_signature.py is correct as-is.
test_directory_connector.py (test_060_user_authentication_adlm):
Docstring-only clarification. Cross-checked against bullseye .172,
trixie .138, and a third ATS .134: three different failure modes
(AD audit on/off, ADLM agent forwarding on/off) prove this is AD test
infrastructure flakiness, not an NGFW regression. No behavior change.
On trixie, UVM returns HTTP 302 for unauthenticated requests via "localhost" but 200 via "127.0.0.1". This broke IPS signature updates (intrusion-prevention-get-updates) and the serial console text UI (ut-textui.py), both of which used hostname="localhost".
curl 8.x (shipped with trixie) resolves localhost to ::1 (IPv6) internally, bypassing the system resolver. When Apache receives an IPv6 loopback connection, uvm_login.py accepted ::1 as local but then searched /proc/net/tcp (IPv4 only) for the socket — never finding it in /proc/net/tcp6 where IPv6 sockets live. This caused all localhost connections via ::1 to get HTTP 302 instead of 200. Fix: when remote_ip is ::1, search /proc/net/tcp6 with the proper 32-char IPv6 hex address. IPv4 path unchanged.
Trixie's unzip prompts for overwrite confirmation unlike bullseye. Clean stale /tmp/system_logs before extracting, add -o flag to force overwrite, and fix missing .zip extension in unzip command.
Trixie mod_python session handling can return non-JSON from /auth/login during warmup. Catch JSONDecodeError and retry instead of crashing.
1.reject invalid suricata variable names in IPS settings sync synchronizeSettingsWithVariables() splits get-config output on '=' and blindly adds any new variable to settings. If suricata.yaml contains corrupted entries (e.g. Python source leaked as a port variable), they persist across restarts. Only accept uppercase variable names matching suricata's convention (HOME_NET, HTTP_PORTS, etc.). 2: tolerate kept-back packages on trixie steady-state updates After trixie upgrade completes, is_trixie_upgrade() returns False but regular updates with changed dependencies still produce kept-back packages. Previously this caused ut-upgrade.py to abort, blocking feature updates on trixie systems. Now tolerate kept-back on any trixie kernel (6.12.x) since dist-upgrade resolves them correctly. 3: guard both directions of IPS variable sync + self-heal create-config.py now skips invalid variable names when writing to suricata.yaml (blocks settings→yaml corruption). Java sync also purges existing invalid entries from settings on startup (self-heal for boxes that already have the corruption from prior upgrades). 4: fix test_031_rule_modify empty rules list after test_030 test_030 deletes its rule at cleanup, leaving rules list empty. test_031 assumes a rule exists at index 0. Add the rule if missing. 5: increase cert upload retry window for mod_python warmup 10 retries × 2s = 20s was insufficient on trixie ATS box where the test suite starts shortly after UVM restart. Increase to 20 × 3s = 60s to accommodate mod_python DbmSession initialization.
Two issues caused test_021/022/023 to fail with 60s timeout in
full ATS runs on trixie:
1. admin.js not on disk: after bookworm->trixie upgrade, UVM holds
admin settings in memory but writes admin.js to disk late in
startup. The HTTP login handler (valid_login) reads from disk
via settings_reader -- file missing means login always rejected.
Fix: flush admin settings to disk via setSettings() JSONRPC if
admin.js is absent before attempting HTTP login.
2. Double-slash URL: get_http_url() returns a trailing slash,
producing //auth/login which Apache on trixie may not route to
the mod_python auth handler. Fix: rstrip('/') on the URL.
Also requires python3-gdbm (added in prior commit to
untangle-apache2-config) to ensure mod_python's DbmSession uses
the gdbm backend instead of dbm.sqlite3 which lacks the
first()/next() API used by session cleanup.
The flush workaround (get+setSettings to force admin.js/system.js to disk) masked the real bug: ats-run.sh wiped settings while UVM was still running after ut-upgrade.py restarted it. With the ATS runner fixed to stop UVM before wiping, the workaround is unnecessary.
…tation
NGFW-15675 changed symlinkRootCerts() to use Java file listing instead
of shell globs for the index*/serial* move (preventing shell injection).
However, it also symlinked index.txt and serial.txt to the timestamped
source directory. When removeCertificate("ROOT") later deletes that
directory, the symlinks break, causing ut-certgen to fail with exit 12
("Error generating signed certificate"). This silently breaks SSL
Inspector MITM cert generation — the app shows RUNNING but cannot
forge per-session certificates, so HTTPS traffic passes uninspected.
Fix: copy index.txt and serial.txt back as real files instead of
symlinking them. Unlike untangle.crt/untangle.key (read-only, safe
to symlink), these are OpenSSL CA database files actively written by
openssl-ca on every MITM cert generation and must always exist at the
top-level cert store path regardless of timestamped directory lifecycle.
Affected: both master and ngfw-release-17.5 (any box that triggers root
CA rotation after NGFW-15675 landed). Workaround for already-broken
boxes: ln -sf UntangleRootCA/index.txt index.txt (and serial.txt) in
/usr/share/untangle/settings/untangle-certificates/
…ot CA rotation" This reverts commit 9111f39.
…tation
NGFW-15675 changed symlinkRootCerts() to use Java file listing instead
of shell globs for the index*/serial* move (preventing shell injection).
However, it also symlinked index.txt and serial.txt to the timestamped
source directory. When removeCertificate("ROOT") later deletes that
directory, the symlinks break, causing ut-certgen to fail with exit 12
("Error generating signed certificate"). This silently breaks SSL
Inspector MITM cert generation — the app shows RUNNING but cannot
forge per-session certificates, so HTTPS traffic passes uninspected.
Fix: copy index.txt and serial.txt back as real files instead of
symlinking them. Unlike untangle.crt/untangle.key (read-only, safe
to symlink), these are OpenSSL CA database files actively written by
openssl-ca on every MITM cert generation and must always exist at the
top-level cert store path regardless of timestamped directory lifecycle.
Affected: both master and ngfw-release-17.5 (any box that triggers root
CA rotation after NGFW-15675 landed). Workaround for already-broken
boxes: ln -sf UntangleRootCA/index.txt index.txt (and serial.txt) in
/usr/share/untangle/settings/untangle-certificates/
The previous self-heal was inside symlinkRootCerts() which only runs when untangle.crt/untangle.key are not symlinks. On boxes where the root CA is already symlinked (normal state), symlinkRootCerts is skipped and broken index.txt/serial.txt symlinks are never repaired. Move the self-heal to the CertificateManagerImpl constructor so it runs unconditionally on every UVM startup, after the symlink gate.
JDK21 shutdown hooks take longer to release NFQUEUE sockets than JDK11. Back-to-back init.d restart causes netcap init failure on the new instance. Split into explicit stop, wait-for-java-dead (60s + kill -9 fallback), start.
Static singletons like WebrootDaemon create a Pulse once and reuse it across app enable/disable cycles. When stop() is called, the Pulse thread exits its run loop and sets state to DEAD. On the next start(), the DEAD state was rejected with IllegalStateException, preventing web-filter (and any app using WebrootDaemon) from ever restarting without a full UVM restart. This affects production customers who disable and re-enable web-filter, and ATS runs where multiple test suites rapidly create/destroy apps sharing the same WebrootDaemon singleton. Allow start() from DEAD state alongside UNBORN and KILLED.
When initial_extra_setup() throws (e.g. web-filter instantiation fails), apps created during setup are left half-instantiated. Subsequent test suites find them "already instantiated" and skip entirely, cascading through the rest of the ATS run. Call final_extra_tear_down() on failure to destroy leftover apps so the next suite starts with a clean state.
- qos-status.py: replace missing runSubprocess() with get_tc_output/ format_tc_output (master's shell-injection-safe version) using ifb_dev - OpenVpnManager.java: revert to master's dataCiphersFallback field approach with defensive colon sanitization
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.