This is an automated email from the ASF dual-hosted git repository.

jason810496 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new e043a279628 Go SDK: pack a bundle that registers no Dags at pack time 
(#74637)
e043a279628 is described below

commit e043a279628a9e13c4a986ad2eeab39604e62825
Author: Jason(Zhe-You) Liu <[email protected]>
AuthorDate: Tue Oct 13 18:50:09 2026 +0100

    Go SDK: pack a bundle that registers no Dags at pack time (#74637)
    
    Co-authored-by: Claude <[email protected]>
---
 go-sdk/cmd/airflow-go-pack/pack.go         |  4 +++-
 go-sdk/cmd/airflow-go-pack/pack_test.go    | 36 ++++++++++++++++++++++++++++++
 task-sdk/docs/airflow-metadata.schema.json |  3 +--
 task-sdk/docs/executable-bundle-spec.rst   |  7 +++---
 4 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/go-sdk/cmd/airflow-go-pack/pack.go 
b/go-sdk/cmd/airflow-go-pack/pack.go
index c09cbe87e1e..068afa9bf1d 100644
--- a/go-sdk/cmd/airflow-go-pack/pack.go
+++ b/go-sdk/cmd/airflow-go-pack/pack.go
@@ -165,7 +165,9 @@ func runPack(stdout, stderr io.Writer, opts *packOptions) 
error {
                return err
        }
        if len(meta.Dags) == 0 && len(meta.DagSourceFiles) == 0 {
-               return fmt.Errorf("bundle exposes no dags: nothing to pack")
+               fmt.Fprintln(stderr, "warning: no Dags or task handlers were 
registered at pack time; "+
+                       "this is expected only if the bundle generates its Dags 
at run time, "+
+                       "and those Dags show the entrypoint source in the Code 
view")
        }
        for dagID, dag := range meta.Dags {
                if len(dag.Tasks) == 0 {
diff --git a/go-sdk/cmd/airflow-go-pack/pack_test.go 
b/go-sdk/cmd/airflow-go-pack/pack_test.go
index 992e1e6da87..e1aafd9801c 100644
--- a/go-sdk/cmd/airflow-go-pack/pack_test.go
+++ b/go-sdk/cmd/airflow-go-pack/pack_test.go
@@ -445,6 +445,42 @@ func TestRunPack_PacksABundleWithOnlyNativeDags(t 
*testing.T) {
        assert.Contains(t, stdout.String(), "task_handler_dags=0, 
native_dags=1")
 }
 
+// A bundle that generates its Dags at run time registers nothing at pack time.
+func TestRunPack_PacksABundleWithNoDags(t *testing.T) {
+       dir := t.TempDir()
+       exe := filepath.Join(dir, "generated")
+       require.NoError(t, os.WriteFile(exe, []byte("generated-binary-bytes"), 
0o755))
+       source := filepath.Join(dir, "main.go")
+       require.NoError(t, os.WriteFile(source, []byte("package main\nfunc 
main() {}\n"), 0o644))
+       meta := filepath.Join(dir, "airflow-metadata.json")
+       require.NoError(t, os.WriteFile(meta, []byte(
+               `{"airflow_bundle_metadata_version":"1.0",`+
+                       
`"sdk":{"language":"go","version":"0.1.0","supervisor_schema_version":"2026-06-16"},`+
+                       `"dags":{}}`,
+       ), 0o644))
+       out := filepath.Join(dir, "bundle")
+
+       var stdout, stderr bytes.Buffer
+       err := runPack(&stdout, &stderr, &packOptions{
+               executable:      exe,
+               source:          source,
+               airflowMetadata: meta,
+               output:          out,
+       })
+       require.NoError(t, err)
+
+       _, gotMeta, err := bundlefooter.Read(out)
+       require.NoError(t, err)
+       assert.Contains(t, string(gotMeta), `entrypoint_path: "main.go"`)
+       assert.Contains(t, string(gotMeta), `path: "main.go"`)
+       assert.Contains(
+               t,
+               stderr.String(),
+               "warning: no Dags or task handlers were registered at pack 
time",
+       )
+       assert.Contains(t, stdout.String(), "task_handler_dags=0, 
native_dags=0")
+}
+
 // --airflow-metadata also accepts a YAML manifest, not only the JSON the
 // binary prints.
 func TestRunPack_AcceptsYAMLMetadataFile(t *testing.T) {
diff --git a/task-sdk/docs/airflow-metadata.schema.json 
b/task-sdk/docs/airflow-metadata.schema.json
index c9c699ba029..c8ae05318fa 100644
--- a/task-sdk/docs/airflow-metadata.schema.json
+++ b/task-sdk/docs/airflow-metadata.schema.json
@@ -57,8 +57,7 @@
     },
     "dags": {
       "type": "object",
-      "description": "Mapping of dag_id to DAG entry. Every dag_id the bundle 
exposes must appear here.",
-      "minProperties": 1,
+      "description": "Mapping of dag_id to the tasks the bundle runs for a 
Python Dag with stub TaskHandler. May be empty, for example when the bundle 
only declares Dag definitions.",
       "additionalProperties": {
         "$ref": "#/$defs/dagEntry"
       }
diff --git a/task-sdk/docs/executable-bundle-spec.rst 
b/task-sdk/docs/executable-bundle-spec.rst
index b8041b6357a..968b35a4417 100644
--- a/task-sdk/docs/executable-bundle-spec.rst
+++ b/task-sdk/docs/executable-bundle-spec.rst
@@ -262,9 +262,10 @@ Top-level keys:
     - ``sha256`` (string, required): the lower-case hexadecimal SHA-256 of the 
file's bytes.
 
 ``dags`` (mapping, required)
-    Mapping of ``dag_id`` to a *DAG entry*. Every ``dag_id`` the bundle
-    exposes MUST appear here. The scanner uses these keys to match a DAG
-    parsing or task-execution request to the bundle that owns it.
+    Mapping of ``dag_id`` to a *DAG entry*, for each Python Dag with stub 
TaskHandler whose tasks the
+    bundle runs. The scanner uses these keys to match a task-execution request 
to the bundle that
+    owns it. The mapping MAY be empty, for example when the bundle only 
declares Dag definitions,
+    because the Dag processor finds those by running the binary.
 
 DAG entry fields:
 

Reply via email to