Skip to content

Latest commit

 

History

History
256 lines (221 loc) · 14 KB

File metadata and controls

256 lines (221 loc) · 14 KB

Changelog

Unreleased

v4.7.1 - 2026-09-21

  • A task that overwrites its own sources is now called out. When a task's commands write files its sources: glob also matches, the checksum changes mid-run, so the task can never be cached. Task now prints a warning naming those files and skips publishing the task's fingerprint and cache entry; previously this was logged only under --verbose.
  • Cache save and push failures are now reported. A cache entry that cannot be archived, written, or pushed prints a warning instead of being logged only under --verbose. An unreachable registry warns once per host; other failures warn per task.

v4.7.0 - 2026-09-21

  • Included tasks share saved fingerprints when their build inputs match, even across separate runs without a build cache. Variables that change commands or declared environment values keep separate entries; namespaced task references still distinguish copies. Checksum values keep the Go fork's format, but filenames differ, so upgrading rebuilds each task once.

v4.6.2 - 2026-09-19

  • A cache transfer no longer fails on one dropped connection to the registry. A pull or push request whose connection could not be made, timed out, or was cut short under the response is now made again a few times, seconds apart, before the cache entry is given up on. A registry answer — a miss, a refusal, a digest that does not match — is still final at once.

v4.6.1 - 2026-09-19

  • Cache archives carry the whole generated tree. Collecting a generates glob for the cache now includes hidden entries — node_modules/.bin and every other dot file or directory under **/* — and stores a symlink to a directory as the link instead of following it into its target, so a restored node_modules runs and a Yarn workspace keeps its links. Fingerprint checksums still see what the shell lists, so .task state is unaffected.
  • Failed cache imports invalidate saved task status. After an import fails, tasks rebuild instead of trusting partially restored outputs. If saved status cannot be removed, Task reports that cleanup failure too.

v4.6.0 - 2026-09-18

  • run: once tasks run once across direct and nested includes. When one Taskfile is included both directly and through another include — the root includes lib, and also app, which itself includes lib — a run: once task in it now runs once for both paths instead of once per path. Go Task v3 treats the nested copy as a separate task.
  • A task included under several namespaces shares one cache entry. vk-registry entries, the build-once lock and the archive's task annotation are keyed by the task's name in the Taskfile that defines it, so the copy reached through a nested include restores what the directly included copy built instead of rebuilding it. Tasks that differ only in their vars, or in the vars their include passes, keep separate entries. Every vk-registry tag changes — the include namespace and label no longer appear in it — and an archive saved by a namespaced or labelled task is rebuilt once, so the first build on this version repopulates the cache. .task fingerprints are unaffected.

v4.5.0 - 2026-09-05

  • A Linux release stays rebuildable for good. The pinned build environment is now one locked package set whose sources stay fetchable indefinitely, replacing hand-pinned Alpine packages that eventually disappear. Rebuilding a release still needs only Docker and ./build.sh; the build-info.txt shipped with each Linux release now records a flake lock: digest in place of apk pins:.

v4.4.0 - 2026-09-03

  • vk-registry caches need only an address and an API key. A cache model can name a vk-registry repository — vk: registry.example/task-cache — and Task derives the cache entries and the build-once lock from it; an optional namespace keeps entries built by different toolchains apart, and a vk that renders empty turns the cache off. The key comes from api_key or TASK_VK_API_KEY; api_key also works on an explicit oci:// cache or vk:// lock, where it outranks any other credential.
  • One vk-registry API key authenticates an explicit oci:// cache and vk:// lock. TASK_VK_API_KEY is sent as a bearer token to oci:// caches. vk:// locks without URL credentials use TASK_VK_LOCK_TOKEN, then fall back to that key or the TASK_CACHE_OCI_USER / TASK_CACHE_OCI_PASSWORD pair.
  • Authenticate transparent-zstd capability probes. The oci:// cache now sends registry credentials when negotiating transparent-zstd uploads, so credential-gated vk-registry servers use that mode instead of compressed-digest uploads.
  • A vk:// lock is released when its task finishes. It used to stay held until its lease expired, making a peer waiting on the same build wait up to 30 s longer than needed.
  • An oci:// cache miss is quiet. A tag the registry does not have was reported as a registry error in verbose output on every miss.
  • A vk:// lock names its holder's machine on the registry even when the shell did not export HOSTNAME, as under a CI job.

v4.3.2 - 2026-09-02

  • Match files with trailing ** globstarget/** now matches the same files as target/**/*, restoring Go Task and bash globstar compatibility for sources:, generates:, and exclude: patterns. These patterns previously matched nothing.
  • Exclude build directories without scanning them — an exclude: such as target/**/* skips matching trees, keeping large excludes fast without changing the matched file set.

v4.3.1 - 2026-08-30

  • task --help lists the flags — it now prints the usage line, every option with its description, and the hint to run task --list-all, instead of a short blurb that pointed back at --help for the flag list.

v4.3.0 - 2026-08-28

  • Linux release binaries are reproducible — each release includes a task-linux-<arch>.build-info.txt manifest for verifying a local rebuild. See reproducible builds.

v4.2.0 - 2026-08-27

  • default is a filter, not a backwards-looking call--migrate now converts both Go spellings, {{ .X | default "y" }} and {{ default "y" .X }}, to {{ X | default("y", true) }}. That second argument makes Jinja's own filter mean what sprig's default means — substituting for any empty value, not only an unset one — so a migrated Taskfile renders what it always did while reading in the natural order. A Go {{ default "y" }} with no value at all now renders y, as sprig does, instead of failing.
  • Breaking: the sprig-ordered default(fallback, value) function is gone. A Taskfile written or migrated against 4.1.0 / 4.1.1 that calls it now fails with unknown function; write the value first and add , trueX | default("y", true).
  • trunc and regexReplaceAll work as filterss | trunc(n) and s | regexReplaceAll(pattern, repl), so a Jinja Taskfile no longer has to spell either as a sprig-ordered call. The functions keep working as before, and a Go Taskfile's {{ .P | trunc 3 }}, which used to fail to render, now works and migrates to {{ P | trunc(3) }}.
  • A file's template dialect now covers the vars: it passes to an includes: entry and the caches: models it defines. A tree partway through --migrate works: the migrated file no longer fails on its own include vars, and a not-yet-migrated task no longer fails on the cache URL it inherits. A file that declares one dialect but writes those in the other used to be read as Go regardless, and now errors — run task --migrate on it.

v4.1.1 - 2026-08-27

  • task --update replaces the binary with a published release — the latest, or --update=<version> for a specific one. It asks before touching anything (--yes skips that), checks the download against the sha256 published beside it, and runs the new binary to confirm it works here before putting it in place. task --update --check only reports what is available, exiting 1 when a newer release exists. A task named update still runs as it always did.
  • install-task.sh installs again — every run used to fail before it downloaded the archive.
  • A failing cache registry or cache lock names the reason — a rejected certificate, a refused connection, a name that does not resolve — instead of only reporting that the registry could not be reached.
  • A vks:// lock trusts the same certificate as the cache, so one registry behind a private CA serves both the cache and the build-once lock. Such a lock could not connect before, and every run took a local lock instead.
  • Go-syntax Taskfiles can call printf and print, so a Taskfile that builds a path out of several variables renders and migrates instead of being rejected as an unsupported construct. printf covers the string-composing verbs (%s, %v, %q, %d, %%, with flags and a width); another verb, a precision, an argument its verb cannot render, or a mismatched argument count is an error.
  • An unsupported Go construct is reported as the {{ … }} that used it — with the line it is on when migrating a whole Taskfile — instead of quoting the string it came from, which under --migrate was the whole file.

v4.1.0 - 2026-08-26

  • Quoted strings in Go-syntax templates keep their dots, so {{ .FILE | replace ".tar.gz" "" }} strips what it was given. Affected tasks re-run once, and a Taskfile already converted by task --migrate --write needs checking by hand.
  • An escaped quote works inside a Go-syntax template string. A Taskfile already converted by task --migrate --write needs checking by hand.
  • Go-syntax templates can call the string helpers directly, not only after a pipe, so {{trimSuffix ".po" .ITEM}} works. splitList was splitting the wrong argument. Affected tasks re-run once.
  • default, title, join, first and last mean the same on either side of a pipe in Go-syntax Taskfiles — most visibly, default substitutes for any empty value, not only an unset one. Jinja Taskfiles keep Jinja's meaning. Affected tasks re-run once, and a Taskfile already converted needs checking by hand.
  • The Go-template deprecation warning no longer runs into the next line.
  • A dependency cycle is reported as one, naming the path (a -> b -> a), instead of running until the process ran out of stack. A task that reaches itself is rejected: calling itself with different vars: still works, but recursion driven by state outside the Taskfile no longer does.
  • Deep dependency trees no longer crash the runner. Thousands of levels run; a runaway recursion stops with an error instead.
  • Tasks start in a different order, so interleaved output can differ. --output group and prefixed still keep each task's output together.
  • A failing dependency no longer stops its siblings starting. Under --failfast they all start and are cancelled when one fails, so a cancelled sibling may leave partial work behind.
  • A failing run stops the commands it leaves behind instead of orphaning them. It cannot tell those from a job a task backgrounded on purpose, so both are stopped; TASK_NO_REAP=1 turns that off.
  • Ctrl-C reaches the commands, not just the runner. The second press is passed on to them, and the third stops them before exiting.
  • A confirmation prompt no longer pauses the rest of the run, and Ctrl-C works while one is waiting.
  • A SIGTERM stops the run at once, exiting 1 — it comes from a supervisor, so there is no second signal to wait for. Ctrl-C keeps its three-press escalation, and watch sessions are unchanged.

v4.0.0 - 2026-08-24

Task is now a Rust program. v4.0.0 is a full rewrite that aims to be drop-in compatible.

Highlights

  • Local deduplicated cache. A content-defined-chunking, zstd-compressed, content-addressed cache (the ocicas crate) backs --export-cache / --import-cache and the OCI cache backend, so shared build outputs are stored and transferred once.
  • Native Jinja templating (opt-in), with migration. Alongside the existing Go text/template syntax, a Taskfile can opt into native minijinja with templater: jinja, unlocking {% for %}, {% if %}, filters, and function-call syntax. The dialect is auto-detected per file; task --migrate converts a Go-syntax Taskfile to Jinja (preview by default, --write to apply).
  • Go template syntax is deprecated. Files that still use it get a one-time warning pointing at task --migrate. Go rendering will be removed in a future release; migration will remain. Suppress the warning with TASK_NO_GO_DEPRECATION=1.
  • vk-registry distributed lock. cache.lock: vk://host/<prefix> takes the build-once lock over the registry's own /lock API, so one vk-registry serves both the oci:// cache and the lock with no separate Redis. Credentials come from the URL (Basic) or $TASK_VK_LOCK_TOKEN (bearer); the lease is renewed by a heartbeat and expires 30 s after a holder goes away.
  • Single static binary. The release build links no system C libraries (musl-static, rustls+ring) and ships as one file.

Intentional differences from Task v3

  • A duplicate task key in a Taskfile is now an error instead of silently taking the last definition.
  • Task env/vars take precedence over the process environment by default. A task-defined env/vars value overrides one already present in the inherited environment; set TASK_X_ENV_PRECEDENCE=0 to restore the old order where the process environment wins.
  • Remote (HTTP) Taskfiles are not supported.

Known gaps

  • Storing cache contents in Redis (cache.url: redis://) is not supported. (The file and OCI cache backends, and the Redis and vk-registry distributed lockscache.lock: redis:// and vk:// — all work.)
  • Syntax highlighting in error snippets.