1.0.0-beta1 is already published as apache-airflow-ts-sdk and its
ts-sdk/1.0.0-beta1 tag is taken, so the first release under the
@apache-airflow/ts-sdk name needs a version of its own.
* Rename TypeScript SDK npm package to @apache-airflow/ts-sdk
* Take the TypeScript SDK release tarball name from npm pack
Building the tarball name by hand duplicates npm's naming rules for scoped
packages and can silently drift from what npm actually writes, so the
release job now uses the filename npm reports.
The example project is not published, so its name does not need to follow
the scoped package rename.
---------
* TS SDK: Bump to 1.0.0-beta1 and align README with the guide
Move the human-in-the-loop docs into the TypeScript SDK guide, describe the
TaskClient methods in a table, and trim the README and the API reference
landing page to a quick start that links to the guide.
* Keep the HITL params warning in the TypeScript SDK guide
---------
A Dag written in TypeScript could not pause and wait for a person,
while Python Dags can with ApprovalOperator and HITLOperator. Airflow
already supports parking a task in awaiting_input and resuming it with
the response for any runtime, so only the TypeScript side was missing.
* TS SDK: add an internal Operator interface for built-in operators
The Dag, the bundle, the serializer and the runtime each named every built-in
operator by hand, and the two runners duplicated the execute_complete and
__fail__ scaffolding. Collapse that into one internal Operator interface with
a shared dispatcher, so a new operator is a single file and no core edit.
No behavior change.
Co-Authored-By: Claude <noreply@anthropic.com>
* TS SDK: align the human-in-the-loop API with Python and add params
The factory and its options now transliterate the Python operators, the way
triggerDagRun already did: hitl() for HITLOperator, assignedUsers, and
ignoreDownstreamTriggerRules plus failOnReject in place of onReject.
Adds params, so a reviewer can edit a drafted value rather than only choose,
with the key check HITLOperator.validate_params_input does on resume.
Human-in-the-loop now lives behind its own export subpath:
import { approval, hitl } from "apache-airflow-ts-sdk/hitl";
Also fixes subject and body not being able to read different inputs, and
rejects executionTimeout on these tasks, which nothing enforced.
Co-Authored-By: Claude <noreply@anthropic.com>
* TS SDK: cover the agent approval flow with an example and e2e tests
An agent drafts something risky, the task parks without holding a worker, a
person approves and edits the draft, and the run continues without re-running
the model. The example Dag stands in for the model so the flow can be checked
without a provider.
The e2e mode could only run Dags declared in Python: the Dag processor had
neither the bundle mount nor Node, so a Dag declared in TypeScript was never
parsed. Both are added to the ts overlay.
Co-Authored-By: Claude <noreply@anthropic.com>
* TS SDK: Address the HITL review: camelCase result, approval form, internals
Reviewers asked for TypeScript names on the result downstream tasks read, and
pointed out that the form example let a rejected rollout run, that an
approval() from a second copy of the package failed only on the first Reject,
and that the operator machinery showed in the public types and API docs.
- The result uses camelCase keys; Airflow's request, response and resume
event keep their snake_case keys.
- The form example asks with approval(), and the README says form values are
not yet checked against their schema.
- dag.task rejects an operator built by another copy of the package.
- HITLResult and HITLUser are type aliases, so the result needs no cast.
- The Operator members are tagged @internal and the factories' input type is
exported as HITLTextArgs, so the API docs no longer show the operator
machinery.
* TS SDK: Make the HITL tests fail when what they guard breaks
Several checks had no test that failed without them, an integration test was
a hand copy of the agent example that had drifted, and two e2e assertions
could not fail because of the SDK.
- Tests cover the rendered-body check, the non-timeout resume reason, the
assigned-user extra-key check and the options-object check.
- A small purpose-built Dag checks that a resume with arg_bindings pulls no
inputs and renders nothing again.
- The agent example no longer returns a fixed modelCalls.
- test_model_step_did_not_run_again is removed: it checked that Airflow does
not re-run a finished upstream task, which the SDK has no way to do.
---------
Co-authored-by: ZHE YOU LIU <zhu424.dev@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
A Dag authored in TypeScript has to describe itself with the same options
Airflow's scheduler reads, and that vocabulary lives in airflow-core's Dag
serialization schema. Hand-listing those options in the SDK would leave two
copies to keep aligned by hand, and the copy the SDK ships would quietly rot
every time core adds, renames, or drops a key.
Deriving them instead makes the drift visible: a new scalar key shows up in the
regenerated diff or fails generation until someone says why the SDK omits it,
and a curated entry that outlives the key it names fails the same way. The
serialization version is the one thing the schema cannot supply, so a core bump
now fails a test in airflow-core rather than producing Dags stamped with a
version core no longer writes.
This follows the policy the Go SDK's TaskSpec generator set and ADR-0008
records, so the three language SDKs expose the same Dag surface for the same
documented reasons.
* Publish TypeScript SDK with trusted credentials
* Support staged TypeScript SDK releases
* Harden TypeScript SDK release publishing
* Lint, test, and document TypeScript SDK releases
Scripts under ts-sdk/scripts/ fell outside the package's lint, format,
and test globs, letting them drift from the rest of the SDK's coding
standards, and running the release input validator's tests through a
second `node --test` invocation split their results away from `pnpm
test`. The release workflow also required a tag to already exist on
apache/airflow before it could be dispatched against that ref, but the
publishing guide never spelled out the commands for that step.
* Fix TypeScript SDK prerelease dist-tag validation
The prerelease-channel regex included the identifier separator hyphen,
so a tag like ts-sdk/1.0.0-rc-1 derived a channel of "rc-" instead of
"rc" and was rejected for a valid npm_tag=rc dispatch. A numeric-only
prerelease identifier also produced a malformed error message that
named the "next" dist-tag twice. Reading the package name from
package.json instead of a second hardcoded literal keeps the two from
drifting apart. The README now notes that a staged release's dist-tag
only moves at npm's later, unvalidated approval step, so staged
versions must be approved in the order they were requested.
* Report the npm version that fails the release preflight
The preflight exited bare on an npm older than 11.15, so a release manager saw
only "Process completed with exit code 1" on the one step whose failure is
least self explanatory. It now names the detected version, the required
version, and where to change the pin.
* Drop the unreachable empty-artifact-directory assertion
The emptiness check ran immediately after mkdir -p on a path under RUNNER_TEMP
on a fresh runner, so it could never fail. The following assertion that exactly
one tarball exists is the one that actually constrains npm pack.
* Keep the release tarball for the approval window
Retention runs from upload rather than from run completion, and this workflow
waits on a human environment approval before the tarball is consumed. One day
lost it whenever approval landed more than a day after dispatch, forcing a full
re-dispatch. Seven days matches the rest of the repository.
* Query the npm dist-tag with the validated package name
The dist-tag preflight named the package with a second hardcoded literal, so a
rename of the published package would have left it querying the old name and
silently comparing against an unrelated dist-tag. It now reuses the name the
validator already reads from package.json. Verifying package identity moves
ahead of the query so the one remaining literal still pins the name before
anything is derived from it.
* Configure one npm trusted publisher for both release paths
The documented setup asked for two trusted-publisher relationships on one
package to make staging and formal publishing mutually exclusive. npm's
registry accepts only one configuration per package, so the second command
fails and the surviving configuration pins a single environment claim that
rejects the other job's publish - a failure that only surfaces after a
maintainer has already approved the environment gate. Both paths now share one
configuration and one environment, and the documentation credits the separation
to the GitHub approval gate that actually provides it.
* Stop naming the next dist-tag twice for next-channel prereleases
A prerelease whose channel is already next, such as ts-sdk/1.0.0-next1,
derived the same dist-tag from both sides of the allowed-tag message and told
the release manager to "use the next or next npm dist-tag". The numeric-only
identifier case was handled earlier; this one shares its shape.
* Verify package contents before packing the release tarball
The packaging check that rejects source, test, and configuration files from the
published tarball only ran when a contributor remembered to invoke it by hand,
so nothing enforced it on the one run where it matters. Running it in the
release build job, before the tarball is created, makes it a gate rather than a
convention while keeping it out of pull request CI.
Depends on #71399, which adds the verify:package script.
* Verify TypeScript SDK package contents
* Add --all-files to verify-ts-sdk-package doc command
* Smoke-test the Dag-authoring entrypoints the package publishes
The consumer smoke test asserted a registerTask export that the SDK no longer
has, so it would have failed every release regardless of whether the tarball
was sound. It now checks the Dag, DagRegistry, and serveDags entrypoints the
documented authoring API is built from, and reports which one is missing
instead of exiting without a message.
* Import every exports subpath in the package smoke test
The check only imported the package root, so the ./coordinator subpath was
confirmed present in the tarball and never actually resolved. A subpath can
ship and still fail to import when its exports conditions are wrong or an
internal import is broken, which is the failure a consumer would hit first.
Deriving the list from the exports keys also means a new subpath is covered
without touching this script.
* Unit-test the TypeScript SDK package verification helpers
The verification ran as top-level statements, so importing the module packed
the SDK and installed it from the registry, and none of the logic that decides
what may ship could be exercised without a full release rehearsal. Splitting
the allowlist, entry-point derivation, pack-metadata parsing, and smoke-test
construction into importable functions behind an entrypoint guard puts that
logic under test, matching the shape of the release input validator.
* Prepare TypeScript SDK 1.0.0-beta1
The first beta needs a publishable unscoped npm identity and consistent release metadata across the SDK, examples, and documentation.
* Keep the TypeScript SDK beta below 1.0
* Bump @types/node from 22.19.17 to 26.1.2 in /ts-sdk
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 22.19.17 to 26.1.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)
---
updated-dependencies:
- dependency-name: "@types/node"
dependency-version: 26.1.2
dependency-type: direct:development
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
* Keep ts-sdk typecheck passing under @types/node 26
@types/node 26 widens the socket "data" event payload to
`string | Buffer`. These sockets never have an encoding set, so the
payload is always a Buffer; annotating the listener parameter says so
instead of forcing a runtime branch that can never be taken.
* Keep ts-sdk/docs pinned to the same @types/node as ts-sdk
The docs toolchain type-checks the SDK's own sources, so a pin that
lags behind ts-sdk resolves those sources against different Node
typings than the SDK is built with. The check-ts-sdk-docs-package-version-in-sync
hook enforces the pairing.
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jarek Potiuk <jarek@potiuk.com>
* Add airflow-ts-pack bundle build tool for TypeScript SDK
* Embed TypeScript bundle metadata as leading comment
* Harden airflow-ts-pack manifest reading and packaging
Address review: strip entry shebangs so the metadata line stays first,
read the manifest via a sentinel line immune to import-time logging,
validate before writing bundle.mjs, make esbuild an optional peer
dependency, and reject null dags manifests.
* Validate embedded metadata size and split manifest out of runtime