You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
deploy confirms before a solution's first import to a target: the first time a solution is imported to an environment that doesn't have it yet, deploy asks for confirmation — worded per managed/unmanaged mode, since Flowline can't switch a target's mode back once set. Doesn't fire for dev (already rejected by the DTAP gate) or when the solution already exists in the target (the existing, non-bypassable managed/unmanaged mismatch guard covers that case). Breaking for CI: a pipeline doing a first-time deploy of a solution to a target now exits 17 unless it already passes --force first-import (or --force all) — add it to existing non-interactive first-deploy scripts.
deploy publishes the packed solution zip to CI natively: on Azure Pipelines, the zip is attached as a build artifact automatically, named <SolutionName>-<Version> so the version is visible in the Artifacts tab without changing the underlying zip's own filename; on GitHub Actions, its resolved path is written to the step output artifact-path-<SolutionName> for the workflow's own actions/upload-artifact step to reference. No new flag, fires regardless of the subsequent import's outcome, and a failure to emit either signal is a warning, never a deploy-blocking error.
[CustomApi(UniqueName = "...")]: override a Custom API's unique name with the complete Dataverse name, publisher prefix included — lets a class migrated from another registration tool (spkl, Daxif) adopt an already-live Custom API in place when Flowline's derived name wouldn't match it. The prefix is validated against the live solution's publisher prefix and push fails with a clear error on mismatch; two Custom APIs resolving to the same final unique name — derived or explicit — now fail the push instead of silently colliding.
// flowline:onchange annotation: bind a web resource function to a specific field's OnChange event, the same way // flowline:onload/onsave bind to the form's OnLoad/OnSave. Scoped per attribute — two annotations targeting different fields on the same form register and update independently instead of clobbering each other. push's dry-run/verbose change report and the rename-aware diagnostics introduced for onload/onsave in 0.10.0 both cover onchange as well.
Tab and IFRAME form events: form-event annotations now also bind to a Tab's TabStateChange event and an IFRAME's OnReadyStateComplete event, scoped by tab name or control id the same way onchange is scoped by attribute. IFRAME control ids match prefix-insensitively, so an annotation can use either the bare suffix a maker actually types or the Maker Portal's fully-prefixed IFRAME_... control name.
[bulkEdit] and [order:N] annotation modifiers: append to any flowline:onload/onsave/onchange annotation. [bulkEdit] (onload only) toggles the form library's "Enable for bulk edit form" setting. [order:N] sets explicit cross-file handler ordering, overriding the default annotation-encounter order — push fails if two annotations for the same event/scope claim the same order value. Dataverse's 50-handler-per-event cap is now enforced before any write.
Push plugin assemblies packaged as a NuGet package (PluginPackage): when the Plugins project's build produces a .nupkg (e.g. pac plugin init's default project shape), push auto-detects it and registers a Dataverse PluginPackage instead of a classic assembly — supports multiple plugin-bearing DLLs in one package, each synced independently. Change detection hashes the whole package, so an unchanged package skips the content write and only syncs each assembly's own drifted steps/Custom APIs. Standalone --pluginFile now also accepts a .nupkg path. New .flowline key PluginPackageMode (Auto default / Nupkg / Dll) controls the behavior: Auto uses a package when the build produced one, else falls back to the classic assembly; Nupkg requires a package and fails loudly if the build didn't produce one; Dll forces the classic path even when a package exists — the only option for on-premises environments, since Dependent Assemblies packages are cloud-only. Orphan cleanup redirects a package-owned assembly's deletion to its parent package (Dataverse rejects a direct delete on a package-owned assembly) and deletes any Custom API still bound to it first. push fails clearly if the build output contains more than one .nupkg (a stale package left over from a previous version bump) and self-heals a .nupkg that's older than the assembly it was built from (NuGet's incremental Pack step can skip regenerating it) by forcing one full rebuild.
Flowline ships as a Claude Code / Codex agent plugin: adds flowline and flowline-migration skills plus marketplace catalogs for both ecosystems, so an agent knows how to drive Flowline commands and how to migrate an existing spkl/Daxif/PACX/ALM Accelerator project before a Flowline project even exists. See the README for install instructions.
Changed
Form event handler merge preserves a foreign handler's position: an out-of-the-box or ISV-authored handler already registered on an event now keeps its original position in the form's handler list instead of always being pushed after Flowline's own handlers — it keeps running exactly where it always ran relative to Flowline-managed handlers.
deploy no longer accepts --managed (breaking change, no deprecation window): managed/unmanaged mode was already a single project-wide setting read from .flowline, decided at clone/sync time — deploy --managed only ever mutated .flowline via a confirm prompt, it was never a genuine per-run override. Configure managed/unmanaged exclusively via clone --managed/sync --managed. config is also dropped from deploy's valid --force specifiers, since it has no remaining config-write hazard.
deploy's artifact-reuse cache now reports its outcome on every run, not just on a hit: a fresh pack used to print nothing, so a cache miss was indistinguishable from a broken feature. Every non---path deploy now prints the real outcome, naming the reason on a miss (no cached build yet, source changed, unresolvable commit, --no-cache, managed-flag mismatch, or a missing artifact file). Projects with Test and/or UAT configured also get a longer "build once, reused across every stage" explanation; on CI the line still reports the real outcome (a self-hosted or persisted-workspace runner can genuinely hit) with a note appended pointing at --path for reusing one build across ephemeral per-stage jobs. Cache mechanics are unchanged — this is messaging-only.