chore(release): v0.16.0 - #324
Open
github-actions[bot] wants to merge 13 commits into
Open
Conversation
…sole migration (#322) * build(logger): swap pino for logtape, add temporal subpath + jest * fix(logger): align @logtape/pretty and @logtape/redaction to 2.2.1 peer range * feat(logger): configureLogging with env formatter, base fields, bigint replacer * feat(logger): OTel-compatible correlation field constants * feat(logger): central redaction (field+pattern+deep+numeric formatter) and promoted supplier redactors * fix(logger): cycle guard in redactObject + password/bearer value backstops * feat(logger): pluggable client sink + minimalSink + browser configure branch * feat(logger): logtape-native public API + correlation helpers + promote provider-workflows redactors * fix(logger): drop getClientSink from public barrel per spec * feat(logger): logtape-backed temporal bridge on @igniter/logger/temporal subpath * build: inject APP_VERSION + SERVICE_NAME per app for service.version base field * fix(ci): pass APP_VERSION build-arg in real deploy build steps * refactor(logger): convert pocket/notifications/temporal/domain callers to native logtape shape Flip remaining pino-style obj-first calls (info({obj}, 'msg')) to LogTape message-first (info('msg', {obj})), and the pocket .child({service}) call to getLogger(['pocket', 'blockchain']). Covers packages/pocket, all three notification channels + notifier, packages/temporal (client, worker, scheduleWatchdog), and one domain handler call whose second arg wasn't a properties record. * refactor(logger): convert workflow app loggers to logtape, wire configureLogging in workers Flip obj-first calls to message-first in both apps' bootstrap.ts/worker.ts and DAL settings, and replace logger.child({context}) with logger.getChild(name) in both DAL.ts constructors and the ScheduleWatchdog wiring in worker.ts. Also call configureLogging({ serviceName }) as the first statement in setupTemporalWorker() for both provider-workflows and middleman-workflows — without it LogTape emits nothing, so the converted workers would type-check but produce zero log output on staging. * refactor(temporal): convert workflowView optional logger hook to logtape shape * refactor(pocket,commons): replace console.* with injected logger (optional, getLogger default) * ci: path-scoped no-console grep guard + advisory eslint rule * fix(ci): no-console guard on portable grep with loud failure modes Replace rg (not preinstalled on ubuntu-latest) with POSIX grep -rEn. Narrow the match pattern to call-shape only so it stops false-positiving on prose mentions of console.* in comments. Handle grep's exit codes explicitly instead of blanket `|| true`, so a broken invocation fails loudly (exit 2) rather than silently reporting a clean guard. Drop the invented, gameable __sanctioned__/** exemption -- packages/logger/src has zero real console calls to exempt. * fix(logger): keep AsyncLocalStorage require out of static bundler resolution Task 11 (#219) Docker/Next.js build validation surfaced a real build break: config.ts's top-level `import { AsyncLocalStorage } from 'node:async_hooks'` was only guarded at the usage site (`runtime === 'node' ? { contextLocalStorage: ... } : {}`), not at the import site. Static imports get resolved by bundlers unconditionally regardless of runtime branching, so any 'use client' component that transitively imports @igniter/logger (e.g. apps/provider's settings Form.tsx -> @igniter/commons/crypto -> @igniter/logger) dragged node:async_hooks into webpack's browser compilation, which has no node: scheme handler -> hard UnhandledSchemeError build failure. Fix: resolve AsyncLocalStorage lazily via a variable-indirected require() (only reached when detectRuntime() === 'node'), typed against LogTape's own ContextLocalStorage interface instead of Node's type, since AsyncLocalStorage already structurally satisfies it. This keeps the specifier out of webpack's static require analysis (same pattern @temporalio/common's own dynamic requires already rely on) without changing any runtime behavior. Verified: logger unit tests (33/33) and check-types green; full `pnpm turbo build` now succeeds for both Next.js apps (provider, middleman); Docker builds for provider-workflows and provider succeed with correct APP_VERSION/SERVICE_NAME at runtime; client and edge bundles carry the loader only as dead code behind the same runtime === 'node' guard, never invoked outside Node. * fix(logger): lazy base-field binding so pre-configure loggers get service fields getLogger() bound base fields via .with(getBaseFields()), which snapshots a plain object at call time. Module-scope loggers (workers' worker.ts roots, notification channels) are created before configureLogging() runs, so they snapshotted {} forever and never carried service.name/service.version. Bind each field via LogTape's lazy() instead, which resolves at record time. Adds a regression test that creates a logger before configureLogging() and asserts the resolved service.name reaches the log record. * feat(apps): wire configureLogging via instrumentation.ts in provider and middleman Neither Next.js app called configureLogging(), so no service.name/version base fields or LogTape sinks were ever wired in either app's server runtime — a full log blackout. Next 15 auto-detects src/instrumentation.ts; register() calls configureLogging() with no args, since serviceName falls back to the SERVICE_NAME env var already set per-app in each Dockerfile. * fix(logger): node18-safe newRequestId + brace-safe temporal bridge + cycle-safe prod formatter - newRequestId: guarded globalThis.crypto?.randomUUID with runtime-assembled node:crypto fallback (Node 18 CI jest has no global crypto) - temporal bridge: escape foreign-message braces (LogTape doubled-brace escape) so JSON blobs render verbatim instead of undefined placeholders - prod NDJSON: safeStringify WeakSet circular guard so cyclic props emit a line with [circular] instead of silently dropping the record * fix(logger): scope bigint serialization to log formatters, drop global prototype patch Delete installBigIntJson (global BigInt.prototype.toJSON patch) which silently changed the Temporal payload boundary (bigint crossed as string instead of throwing loud, which activities/index.ts relies on). bigint->string now handled only inside prodJsonReplacer; pretty path verified not to throw. Test asserts the global patch is gone (JSON.stringify on bigint throws again at global scope). * fix(apps): configureLogging in seeds + move APP_VERSION to runner stage + template-literal log props - bootstrap seeds: await configureLogging() at top of main so getLogger() calls hit configured sinks instead of a no-sink blackhole - Dockerfiles (all 4): move ARG/ENV APP_VERSION to the final/runner stage so a per-deploy version bump stops invalidating install/build layers - convert JSON/error/reason template-literal log messages to props (brace-safe): CompareSupplierServiceConfigHandler, middleman provider service, and the four SupplierStatus/Remediation child-workflow-failed logs * docs: align spec/readme/env samples with logtape levels - spec §0: @logtape/redaction 1.3.6->2.2.1; bigint row = scoped-in-formatters (no global patch); edge-output row documents accepted F2 console-routing deviation - READMEs + .env.sample: LOG_LEVEL valid LogTape levels (warning not warn), default debug - append adversarial-panel fix section to task-11 report * feat(logger): render structured properties in dev pretty output Dev pretty formatter now uses getPrettyFormatter({ properties: true }) so payload-carrying debug lines (drizzle query/params) are visible locally. Constant base fields (service.*, env, runtime) are dropped from dev rendering only — prod NDJSON keeps them for the collector. Also drop the dangling colon from the drizzle query log message. * feat(logger): LOG_FORMAT env knob; localnet defaults to NDJSON LOG_FORMAT=json|pretty overrides the NODE_ENV-derived output format. Localnet dev ConfigMaps set json for all four apps: one-line NDJSON is agent/jq-friendly for log-driven debugging and gives format parity with what Loki will ingest in prod. Laptop dev (env unset) stays pretty. * fix(logger): store base fields and client sink in global symbol registry Next.js can instantiate this package twice on the server (transpilePackages copy + dist CJS copy via workspace deps). LogTape survives that via Symbol.for globals, but our module-level state did not: configureLogging() populated one copy's baseFields while @igniter/db's logger read the other copy's empty object, so lazy base fields resolved to undefined and dropped out of NDJSON records. Both stores now use the same Symbol.for pattern LogTape itself uses. * fix(apps): pass explicit serviceName in Next instrumentation Matches the workers' bootstrap pattern; without it, localnet/dev pods (no prod-image SERVICE_NAME env) stamped service.name=unknown. * fix(logger): drop dynamic requires — hard build errors under Turbopack Turbopack analyzes every require() call site and fails the build on non-literal specifiers ('Can't resolve <dynamic>'); webpack only warned. newRequestId now uses global Web Crypto with a pure-JS v4 fallback (no node builtin at all — the id is a correlation token, not a credential). loadContextLocalStorage switches to eval('require'), the escape hatch opaque to both bundlers, still node-branch-guarded and fail-soft. * fix(logger): static async_hooks import via dedicated module + browser-field substitution Third and final form of the ALS loading strategy. Dynamic-specifier require broke Turbopack ('Can't resolve <dynamic>'); eval('require') broke the Next Edge compile ('Dynamic Code Evaluation not allowed'). context-storage.ts now imports node:async_hooks STATICALLY — the Edge runtime supports AsyncLocalStorage natively — and package.json's top-level browser field substitutes a no-op for client bundles, which webpack and Turbopack both honor. No dynamic resolution anywhere. * fix(db): redact query params for sensitive tables, truncate long values Drizzle's logQuery receives positional params, invisible to the logger's key-name-based redaction — an insert into keys emitted the encrypted privateKey blob verbatim (found auditing real localnet flows). Queries touching secret-bearing tables (keys, notification_channels, smtp_configuration, auth tables) now log '[redacted]' params; long string params elsewhere are truncated. * feat(workflows): migrate remaining console + log-quality pass (#218) Migrate the last 14 raw console.* calls in middleman-workflows (13) and provider-workflows (1) to structured logging: @temporalio/activity log in activities, injected Logger in the (unused) Blockchain lib class, @temporalio/workflow log in worker.ts's own error path. Log-quality pass from the localnet debuggability audit: - executeTransaction now logs the broadcast result (transactionId, hash, type) - applyVerificationDecision now logs the verify verdict (transactionId, hash, success, code, gasUsed) instead of leaving it silent - ExecuteTransaction workflow logs transactionId/hash on every branch instead of only embedding transactionId in the workflow_id string - ExecutePendingTransactions/VerifyPendingTransactions (both apps) log a single debug line on 0-pending instead of staying silent - remediateSupplier's no-op "Bye!" line demoted info->debug (was ~1,150 INFO/2h); SupplierRemediationByRange's Execution Ended summary gains keysChecked/remediated counts as the aggregation point - indexerApiUrl-missing warns collapse to once-per-process via a module-level guard in the activity file (never in the workflow sandbox) * feat(middleman): request-id correlation via edge middleware + server helper Adds withLogging()/runWithRequestContext() (packages/middleman/src/lib/logging) so route handlers and server actions bind request_id for the duration of the call. middleware.ts now reads/mints x-request-id and propagates it on both the forwarded request (edge -> node continuity) and the response, without changing the existing NextAuth redirect-if-unauthenticated semantics. * feat(middleman): migrate server console.* to structured logger + quality pass Server actions, DAL, auth, API routes, and seed scripts now use getLogger(['middleman', <area>]) instead of raw console.*. Notable quality changes (audit items 3/6/8): - Stake.ts/Unstake.ts had zero logs; add request/created op anchors ({ownerAddress, providerId, transactionId}) so app-side stake/unstake actions correlate with the workflow-side trace. - provider-rpc/route.ts: replaced 8 decorative console.log/error with leveled logs, one debug-level redactObject() dump of the outbound payload, and a single info-level completion line with status+durationMs instead of multiline JSON dumps. - auth.ts (SIWP authorize): dropped raw logging of signature/message/ publicKey (secrets/auth material); logs domain + address only. - ImportSuppliers.ts: dropped addresses from the "skipped" warn (count only); added create/status/complete lifecycle logs. - Wrapped the touched action entry points (Stake, Unstake, ImportSuppliers, Providers) in runWithRequestContext() and the touched routes (health, provider-rpc) in withLogging() for request_id correlation. * feat(middleman): migrate client component console.* to structured logger 'use client' components/forms and the browser-side provider RPC helper now use getLogger() (browser-safe sink) instead of console.error/log for error paths and swallowed catches, with the entity that makes the line debuggable (ownerAddress, provider identity, attemptId) attached as structured props. Cleanup-only per spec — client observability stays out of scope. * feat(provider): request-id correlation via edge middleware + server helper Mirrors apps/middleman's pattern: withLogging()/runWithRequestContext() propagate x-request-id from the edge middleware into route handlers and server actions. withAuth (the single chokepoint every provider server action funnels through) binds correlation for the whole action call. * refactor(provider): migrate signature validation + suppliers/status/health routes to logger lib/utils/routes.ts collapses the 17-line-per-request signature validation trace into a single debug line ({delegator, identity, verified}) — never logging the X-Middleman-Signature/Identity header values (audit item 6). Suppliers routes (stake/release/unstaking/suppliers/address-groups) log {supplierAddresses, ownerAddress, delegatorIdentity} at the entities that make a failure debuggable, wrapped with withLogging for correlation (audit item 5). auth.ts, status and health routes get the same console->logger swap with no control-flow changes. * refactor(provider): migrate import-suppliers routes + add key-imported event import-suppliers/{submit,request,status} now log {attemptId, ownerAddress, delegatorIdentity, addressCount} at request outcomes instead of a console line per branch, wrapped with withLogging for correlation (audit item 8). actions/Keys.ts ImportKeys emits `key imported` per inserted key ({address, ownerAddress, state}) at the DB insert boundary — the "3am debugger" event the audit flagged as missing (audit item 7). * refactor(provider): migrate bootstrap-seed/seed + adr36/users to logger bootstrap-seed.ts collapses 35 per-step console lines into per-section info summaries with per-item debug detail (region/relay-miner/service/ address-group/delegator/channel counts) — never logging env or key material. db/seed.ts, adr36 signature verification, and the users DAL get the same console->logger swap. * refactor(provider): migrate client component console.* to structured logger Cleanup-only per spec §10.3 (category 5): every client component swaps console.error(msg, err) for a module-scoped getLogger(['provider','ui',...]) log.error(msg, { error }). Also drops two leftover dev debug console.log lines (ConfigureAppSettings, ConfigureDelegators) and promotes the ImportProcess "invalid file" console.log to a proper debug-level log with error context, since it's a real validation-failure path, not dev spew. * fix(provider): truncate delegator identity in log props per spec §7 * ci: no-console guard repo-wide + final validation * refactor(ui): migrate console to logger, guard packages/ui * refactor(logs): app db categories + demote per-item cron noise to debug - getLogger() in middleman/provider db/index.ts + middleman bootstrap-seed was emitting logger:"" (root category); scoped to ['<app>','db']. - remediateSupplier/upsertSupplierStatus per-item start/query/update/done lines (~600 lines/30m dominant INFO source) demoted to debug in both provider-workflows and middleman-workflows. - middleman-workflows SupplierStatusByRange had no per-range aggregation log (provider-workflows already had one); added "supplier sync range done" at info with keysChecked/upserted. - transaction verified log: dropped code/gasUsed when undefined (degraded-RPC success path had no hash evidence) instead of logging null; added txn.type since it's readily available. * fix(logger): redact snake_case secret fields; single-pass brace escape Redaction patterns were camelCase-anchored, so snake_case secrets (private_key, api_key, access_token, signer_private_key, seed_phrase, set_cookie, ...) leaked through the sink — including our Temporal bridge's snake_cased meta. Tolerate underscores between words in each pattern; public_key still survives (locked rule). temporal escapeBraces now does a single .replace(/[{}]/g, m => m+m) so already-doubled braces are not re-doubled. * fix(apps): configure browser LogTape; drop unauth-redirect to debug instrumentation.ts register() runs server/edge only, so client-component logs went into an unconfigured LogTape and were silently dropped. Add src/instrumentation-client.ts (Next.js 15 client bootstrap) to both apps; it calls configureLogging which wires the browser sinks. Also lower the 'unauthenticated request redirected' middleware log from info to debug — bot/asset probing made it noise. * fix(scripts): make no-console guard default-safe with exclusions list Old guard only scanned an allowlist, so any unmigrated path nobody added was silently ignored. Now scan every apps/*/src and packages/*/src by default, minus an explicit prefix-exclusions list (renamed no-console-allowlist.txt -> no-console-exclusions.txt). packages/logger/src is not excluded (verified zero console writers). Exit-code discipline kept. * fix(logger): harden redaction + console guard per review Applies Miguel's PR #322 review findings (all latent, none active today): - browser/client sinks get the same value-pattern backstop as node: new redactSinkByPattern scrubs SECRET_VALUE_PATTERNS from record message parts and string property values, since the library's redactByPattern only wraps TextFormatters and browser sinks have none - Bearer free-text pattern is now case-insensitive (lowercase 'authorization: bearer <tok>' header dumps had no backstop) - botToken/webhookUrl/encryptionKey (+ snake_case) join the secret field set - console guard: exclusions now anchor to the path field only (a violation whose content mentioned an excluded path was silently dropped) and the method alternation covers the full console surface (table/dir/assert/group/...), with known blind spots documented Not applied: exports 'browser' condition (review LOW 3) — exports cannot remap the internal relative context-storage import and a self-reference subpath doesn't typecheck under classic moduleResolution; decision documented in config.ts.
…UI (#323) * fix(temporal): recreate schedules whose scheduler workflow is corrupt A schedule whose internal scheduler workflow has a Workflow Task in failed state rejects describe/update/trigger with FAILED_PRECONDITION, which crash-looped the worker at bootstrap (ensureSchedule rethrow) and made the watchdog skip the schedule forever. Delete+recreate is the only heal for that state. - isCorruptSchedule: gRPC code 9 + WFT-failed message, walking the cause chain (the SDK's ServiceError hides the code in error.cause — this also fixes isNotFound/isTransient missing every wrapped schedule-client error) - recreateCorrupt: write-ahead recordRecreate -> delete -> create -> resetOnRecreate, never throws; wired into all five schedule RPC sites (bootstrap describe/drift-update, heal update/trigger, watchdog tick) * feat(workflows-ui): pause/resume/recreate schedule actions Gives operators a fast manual exit for stuck or corrupt schedules straight from the admin Workflows > Schedules tab, in both apps. - PauseSchedule/ResumeSchedule/RecreateSchedule server actions (owner-only) mirrored in provider and middleman - Recreate is delete-only on purpose: canonical config lives in the worker, whose watchdog recreates the schedule within one tick and resets heal counters; NOT_FOUND on delete is treated as success - pause/unpause on a corrupt schedule surfaces a hint to use Recreate - SchedulesTab: per-row buttons behind optional WorkflowsActions members, confirm dialogs, schedule-scoped error reporting - isCorruptSchedule/isNotFound re-exported via workflow-view subpath (apps must not import the package root: it drags @temporalio/worker) * fix(temporal): cap+backoff+page the corrupt-schedule recreate loop The corrupt/NOT_FOUND recreate path had no breaker, no backoff, and never paged: an incurable corruption thrashed delete+recreate every tick forever, wiping run history, while the UI rendered the schedule green (describe() fails -> liveness undefined -> fell through to healthy). - New knob maxRecreateAttempts (SCHEDULE_WATCHDOG_MAX_RECREATE_ATTEMPTS, default 3), distinct from recreateAfter (the ladder's stale-escalation knob): at the cap, setUnhealthy(true) + halt the recreate loop. - Exponential backoff between recreates via a sibling eligibility map (backoffBaseMs * 2^recreations, capped), so the ladder's map and resets never clobber it. - Healthy verdict clears the unhealthy flag + recreate backoff so a genuinely-recovered schedule recovers its status. - Tighten the ScheduleAlreadyRunning swallow in recreateCorrupt: re-describe once after the swallow; only resetOnRecreate if it now describes (the write-ahead recordRecreate keeps the attempt counted otherwise). - mapScheduleToHealth: no live verdict (describe() failed fallback) renders 'unknown', not green; SchedulesTab badge maps unknown -> outline. - LOW5: NOT_FOUND branch now passes the store through ensureSchedule. * fix(temporal): operator+episode reset for the recreate breaker; bound verify-describe * fix(temporal): episode breaker reset requires confirmed autonomous fire healthy-verdict describe alone doesn't prove recreate cured a corrupt schedule -- infancy grace lets a freshly recreated, still-broken schedule read healthy before it ever fires. Unconditionally zeroing `recreations` there re-opens the silent recreate-loop the breaker exists to stop. Move both the recreate-breaker reset and the unhealthy clear into the existing hasAutonomousFire-gated branch, alongside the ladder reset -- only a confirmed autonomous fire is proof.
Lock table headers while scrolling in both apps: DataTable opts in by default, and the hand-rolled tables (activity, chain overview, provider breakdown, workflows) get bounded scroll boxes. #317 Consolidate multi-table screens into tabs: middleman Suppliers (Suppliers/Activity/Overview) and provider Keys (Keys/Activity), with the active tab persisted in the URL. #317 Surface the failure reason on failed transactions in both apps’ tables, reading the log/message columns through a shared failureReasonDisplay helper. #317 Add server-side filtering to notification history (event type, read/unread, channel) in both apps; the unread badge count stays unfiltered. #317 Make the left sidebar collapsible to an icon rail with a header toggle, hidden on the landing/auth pages. #317 Add unit tests for the notification filter conditions (both apps) and the shared failure-reason helper. #317
- provider: restore UUID search on notifications (re-add enableSearch) - provider/middleman: surface pending activity on the Activity tab by lifting the pending query above the Radix tab boundary and wiring TabsBadge — the poll was trapped in the unmounted tab, so pending stake/unstake was invisible on the default tab - db: extract shared buildNotificationEventFilterConditions to @igniter/db/notifications; both DAL copies now delegate (dedup) - commons: extract isInternalPath to @igniter/commons/utils; Sidebar and SidebarTriggerGate share it (dedup)
Gate the interval on byKey the same way middleman's SuppliersTabs gates its poll: only poll while there's pending activity, otherwise stop. byKey is the badge's own source, so the poll and badge can't diverge.
-Show friendly on-chain failure reasons in transaction tables Failed transactions previously surfaced only the raw ABCI log (or a generic "Unknown error"), hard to read and duplicated in both the table cell and the detail drawer. Thread the chain's own error text end to end and map known Cosmos SDK error codes to short human-readable messages, shown through a single copyable popover.
The chain already defines RPCType.COMET_BFT = 5 but the app layer whitelisted only the four original types, so operators could not configure CometBFT endpoints for their services. - add COMET_BFT to labelByRpcType and validRpcTypes (cascades to server-side validation, dialogs, and table chips) - extend the endpoint zod enum in AddOrUpdateServiceDialog to the fifth type; the Add Protocol cap follows validRpcTypes.length - map COMET_BFT to scheme "https" and URL token "cometbft" so the default endpoint hostname no longer collides with JSON_RPC - unit tests for both switch functions
* ci: run the test suite in the quality job The quality job ran prettier, lint, build and check-types, but never turbo test — so a green CI said nothing about the 23 test tasks in the workspace. PR #326 was a behavioural fix backed entirely by tests that CI never executed. turbo test costs ~18s locally: its dependsOn is ^build (dependencies only), so the apps' Next builds are not repeated. * ci: use pull_request_target for the staging deploy A pull_request event raised by a PR from a fork gets a read-only GITHUB_TOKEN and no secrets, whatever the permissions block says. When PR #326 (external contributor) was merged, all four build-push jobs failed with 'denied: installation not allowed to Write organization package' and post-deploy was skipped, leaving the release branch out of sync until the deploy was re-run manually via workflow_dispatch. pull_request_target runs in the base-repo context with a read/write token, and keeps github.event.pull_request.labels so the existing 'release' label gate is unchanged. The usual pull_request_target hazard does not apply: both checkouts pin ref: staging, never the PR head, and the job only runs post-merge. * chore(k8s): drop the orphaned middleman-workflows mainnet overlay Real deployments come from pnf-ops (middleman side) and the docker-compose example (operator side). This overlay was last written by the release automation in v0.11.2 (2026-05-18) and has been frozen at that image tag through six releases; deploy-production.yml no longer references it. Its only remaining effect was to read as authoritative production config while declaring NODE_ENV=development and LOG_LEVEL=debug, both inherited from base — which is wrong, and misleading to anyone auditing prod. Tilt is unaffected: every k8s/apps/*/Tiltfile builds ./overlays/dev. * ci: revert the duplicate test step Reverts e0111e9. The quality job already ran `pnpm turbo test` (ci.yml lines 79-80, right after Type check); that commit added a second, identical step. Its premise — that CI never ran the tests — came from a truncated read of the workflow, not from the file. Squash-and-merge collapses this pair away.
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.
Release v0.16.0
Version bump:
release:minorPrevious version: v0.15.0
What happens on merge
0.16.0+latestv0.16.0Auto-prepared by prepare-release workflow