You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by ka...@apache.org on 2025/09/15 21:38:54 UTC
(airflow) branch v3-1-test updated (ba0f359b310 -> 50088d4d54a)
This is an automated email from the ASF dual-hosted git repository.
kaxilnaik pushed a change to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
discard ba0f359b310 Front end for hitl endpoint update (#55674)
discard 64f03d07305 refactor(hitl): make hitl under task instance (#55603)
discard 24ad1b6fe91 Fix task log URL generation with various `base_url` formats (#55699)
discard 5f3ad688d74 #55020 gantt view is not getting updatedin realtime (#55130)
discard 3c4af224c7d fix(docker/entrypoint_prod.sh): prevent the script from code 2 after db migrate success (#52928)
discard 7705559befe Update 3.1.0 release notes based on latest cherry-picks
new f021bba05b5 fix(docker/entrypoint_prod.sh): prevent the script from code 2 after db migrate success (#52928)
new 868748d2fde #55020 gantt view is not getting updatedin realtime (#55130)
new 09560358e06 Fix task log URL generation with various `base_url` formats (#55699)
new 1175d5108c0 refactor(hitl): make hitl under task instance (#55603)
new f6377f66954 Front end for hitl endpoint update (#55674)
new 50088d4d54a Update 3.1.0 release notes based on latest cherry-picks
This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version. This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:
* -- * -- B -- O -- O -- O (ba0f359b310)
\
N -- N -- N refs/heads/v3-1-test (50088d4d54a)
You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.
Any revisions marked "omit" are not gone; other references still
refer to them. Any revisions marked "discard" are gone forever.
The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
RELEASE_NOTES.rst | 1 +
reproducible_build.yaml | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
(airflow) 04/06: refactor(hitl): make hitl under task instance (#55603)
Posted by ka...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kaxilnaik pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 1175d5108c0f0b3a5fb0640e9cc891619c5c0c04
Author: Wei Lee <we...@gmail.com>
AuthorDate: Tue Sep 16 05:32:30 2025 +0800
refactor(hitl): make hitl under task instance (#55603)
(cherry picked from commit a9eecaf47305dc2ce87e83bc246039644a53b3e3)
---
.../src/airflow/api_fastapi/common/parameters.py | 33 +--
.../core_api/openapi/v2-rest-api-generated.yaml | 46 ++--
.../api_fastapi/core_api/routes/public/__init__.py | 4 +-
.../api_fastapi/core_api/routes/public/hitl.py | 30 +--
.../src/airflow/ui/openapi-gen/queries/common.ts | 60 ++---
.../ui/openapi-gen/queries/ensureQueryData.ts | 110 ++++-----
.../src/airflow/ui/openapi-gen/queries/prefetch.ts | 110 ++++-----
.../src/airflow/ui/openapi-gen/queries/queries.ts | 160 ++++++-------
.../src/airflow/ui/openapi-gen/queries/suspense.ts | 110 ++++-----
.../ui/openapi-gen/requests/services.gen.ts | 237 +++++++++----------
.../airflow/ui/openapi-gen/requests/types.gen.ts | 258 ++++++++++-----------
.../core_api/routes/public/test_hitl.py | 119 +++++-----
12 files changed, 622 insertions(+), 655 deletions(-)
diff --git a/airflow-core/src/airflow/api_fastapi/common/parameters.py b/airflow-core/src/airflow/api_fastapi/common/parameters.py
index c6ff8aa6f46..896c00d487d 100644
--- a/airflow-core/src/airflow/api_fastapi/common/parameters.py
+++ b/airflow-core/src/airflow/api_fastapi/common/parameters.py
@@ -987,14 +987,14 @@ QueryHITLDetailTaskIdPatternSearch = Annotated[
)
),
]
-QueryHITLDetailDagRunIdFilter = Annotated[
- FilterParam[str],
+QueryHITLDetailTaskIdFilter = Annotated[
+ FilterParam[str | None],
Depends(
filter_param_factory(
- TaskInstance.run_id,
- str,
- filter_name="dag_run_id",
- ),
+ TaskInstance.task_id,
+ str | None,
+ filter_name="task_id",
+ )
),
]
QueryHITLDetailSubjectSearch = Annotated[
@@ -1025,7 +1025,6 @@ QueryHITLDetailResponseReceivedFilter = Annotated[
)
),
]
-
QueryHITLDetailRespondedUserIdFilter = Annotated[
FilterParam[list[str]],
Depends(
@@ -1050,23 +1049,3 @@ QueryHITLDetailRespondedUserNameFilter = Annotated[
)
),
]
-QueryHITLDetailDagIdFilter = Annotated[
- FilterParam[str | None],
- Depends(
- filter_param_factory(
- TaskInstance.dag_id,
- str | None,
- filter_name="dag_id",
- )
- ),
-]
-QueryHITLDetailTaskIdFilter = Annotated[
- FilterParam[str | None],
- Depends(
- filter_param_factory(
- TaskInstance.task_id,
- str | None,
- filter_name="task_id",
- )
- ),
-]
diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
index 7c8bba4e9aa..e853fcbd386 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
+++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v2-rest-api-generated.yaml
@@ -7956,10 +7956,10 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
- /api/v2/hitlDetails/{dag_id}/{dag_run_id}/{task_id}:
+ /api/v2/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/{map_index}/hitlDetails:
patch:
tags:
- - HumanInTheLoop
+ - Task Instance
summary: Update Hitl Detail
description: Update a Human-in-the-loop detail.
operationId: update_hitl_detail
@@ -7986,11 +7986,10 @@ paths:
type: string
title: Task Id
- name: map_index
- in: query
- required: false
+ in: path
+ required: true
schema:
type: integer
- default: -1
title: Map Index
requestBody:
required: true
@@ -8037,7 +8036,7 @@ paths:
$ref: '#/components/schemas/HTTPValidationError'
get:
tags:
- - HumanInTheLoop
+ - Task Instance
summary: Get Hitl Detail
description: Get a Human-in-the-loop detail of a specific task instance.
operationId: get_hitl_detail
@@ -8064,11 +8063,10 @@ paths:
type: string
title: Task Id
- name: map_index
- in: query
- required: false
+ in: path
+ required: true
schema:
type: integer
- default: -1
title: Map Index
responses:
'200':
@@ -8101,10 +8099,10 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
- /api/v2/hitlDetails/:
+ /api/v2/dags/{dag_id}/dagRuns/{dag_run_id}/hitlDetails:
get:
tags:
- - HumanInTheLoop
+ - Task Instance
summary: Get Hitl Details
description: Get Human-in-the-loop details.
operationId: get_hitl_details
@@ -8112,6 +8110,18 @@ paths:
- OAuth2PasswordBearer: []
- HTTPBearer: []
parameters:
+ - name: dag_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Dag Id
+ - name: dag_run_id
+ in: path
+ required: true
+ schema:
+ type: string
+ title: Dag Run Id
- name: limit
in: query
required: false
@@ -8138,14 +8148,6 @@ paths:
default:
- ti_id
title: Order By
- - name: dag_id
- in: query
- required: false
- schema:
- anyOf:
- - type: string
- - type: 'null'
- title: Dag Id
- name: dag_id_pattern
in: query
required: false
@@ -8158,12 +8160,6 @@ paths:
title: Dag Id Pattern
description: "SQL LIKE expression \u2014 use `%` / `_` wildcards (e.g. `%customer_%`).\
\ Regular expressions are **not** supported."
- - name: dag_run_id
- in: query
- required: false
- schema:
- type: string
- title: Dag Run Id
- name: task_id
in: query
required: false
diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/__init__.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/__init__.py
index 6db86ce2327..65cdbef6642 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/__init__.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/__init__.py
@@ -37,7 +37,7 @@ from airflow.api_fastapi.core_api.routes.public.dag_warning import dag_warning_r
from airflow.api_fastapi.core_api.routes.public.dags import dags_router
from airflow.api_fastapi.core_api.routes.public.event_logs import event_logs_router
from airflow.api_fastapi.core_api.routes.public.extra_links import extra_links_router
-from airflow.api_fastapi.core_api.routes.public.hitl import hitl_router
+from airflow.api_fastapi.core_api.routes.public.hitl import task_instances_hitl_router
from airflow.api_fastapi.core_api.routes.public.import_error import import_error_router
from airflow.api_fastapi.core_api.routes.public.job import job_router
from airflow.api_fastapi.core_api.routes.public.log import task_instances_log_router
@@ -84,7 +84,7 @@ authenticated_router.include_router(task_instances_log_router)
authenticated_router.include_router(dag_parsing_router)
authenticated_router.include_router(dag_tags_router)
authenticated_router.include_router(dag_versions_router)
-authenticated_router.include_router(hitl_router)
+authenticated_router.include_router(task_instances_hitl_router)
# Include authenticated router in public router
diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py
index c444a759ef3..60d9f99fab9 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/public/hitl.py
@@ -28,9 +28,7 @@ from airflow.api_fastapi.auth.managers.models.resource_details import DagAccessE
from airflow.api_fastapi.common.db.common import SessionDep, paginated_select
from airflow.api_fastapi.common.parameters import (
QueryHITLDetailBodySearch,
- QueryHITLDetailDagIdFilter,
QueryHITLDetailDagIdPatternSearch,
- QueryHITLDetailDagRunIdFilter,
QueryHITLDetailRespondedUserIdFilter,
QueryHITLDetailRespondedUserNameFilter,
QueryHITLDetailResponseReceivedFilter,
@@ -56,7 +54,11 @@ from airflow.models.dagrun import DagRun
from airflow.models.hitl import HITLDetail as HITLDetailModel, HITLUser
from airflow.models.taskinstance import TaskInstance as TI
-hitl_router = AirflowRouter(tags=["HumanInTheLoop"], prefix="/hitlDetails")
+task_instances_hitl_router = AirflowRouter(
+ tags=["Task Instance"],
+ prefix="/dags/{dag_id}/dagRuns/{dag_run_id}",
+)
+task_instance_hitl_path = "/taskInstances/{task_id}/{map_index}/hitlDetails"
log = structlog.get_logger(__name__)
@@ -100,8 +102,8 @@ def _get_task_instance_with_hitl_detail(
return task_instance
-@hitl_router.patch(
- "/{dag_id}/{dag_run_id}/{task_id}",
+@task_instances_hitl_router.patch(
+ task_instance_hitl_path,
responses=create_openapi_http_exception_doc(
[
status.HTTP_403_FORBIDDEN,
@@ -165,8 +167,8 @@ def update_hitl_detail(
return HITLDetailResponse.model_validate(hitl_detail_model)
-@hitl_router.get(
- "/{dag_id}/{dag_run_id}/{task_id}",
+@task_instances_hitl_router.get(
+ task_instance_hitl_path,
status_code=status.HTTP_200_OK,
responses=create_openapi_http_exception_doc([status.HTTP_404_NOT_FOUND]),
dependencies=[Depends(requires_access_dag(method="GET", access_entity=DagAccessEntity.HITL_DETAIL))],
@@ -189,12 +191,14 @@ def get_hitl_detail(
return task_instance.hitl_detail
-@hitl_router.get(
- "/",
+@task_instances_hitl_router.get(
+ "/hitlDetails",
status_code=status.HTTP_200_OK,
dependencies=[Depends(requires_access_dag(method="GET", access_entity=DagAccessEntity.HITL_DETAIL))],
)
def get_hitl_details(
+ dag_id: str,
+ dag_run_id: str,
limit: QueryLimit,
offset: QueryOffset,
order_by: Annotated[
@@ -220,9 +224,7 @@ def get_hitl_details(
session: SessionDep,
# ti related filter
readable_ti_filter: ReadableTIFilterDep,
- dag_id: QueryHITLDetailDagIdFilter,
dag_id_pattern: QueryHITLDetailDagIdPatternSearch,
- dag_run_id: QueryHITLDetailDagRunIdFilter,
task_id: QueryHITLDetailTaskIdFilter,
task_id_pattern: QueryHITLDetailTaskIdPatternSearch,
ti_state: QueryTIStateFilter,
@@ -244,14 +246,16 @@ def get_hitl_details(
)
)
)
+ if dag_id != "~":
+ query = query.where(TI.dag_id == dag_id)
+ if dag_run_id != "~":
+ query = query.where(TI.run_id == dag_run_id)
hitl_detail_select, total_entries = paginated_select(
statement=query,
filters=[
# ti related filter
readable_ti_filter,
- dag_id,
dag_id_pattern,
- dag_run_id,
task_id,
task_id_pattern,
ti_state,
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
index d4ffa8098f9..3a937cdd85f 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
@@ -1,7 +1,7 @@
// generated with @7nohe/openapi-react-query-codegen@1.6.2
import { UseQueryResult } from "@tanstack/react-query";
-import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagParsingService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, HumanInTheLoopService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, Structu [...]
+import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagParsingService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, StructureService, TaskInstance [...]
import { DagRunState, DagWarningType } from "../requests/types.gen";
export type AssetServiceGetAssetsDefaultResponse = Awaited<ReturnType<typeof AssetService.getAssets>>;
export type AssetServiceGetAssetsQueryResult<TData = AssetServiceGetAssetsDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
@@ -552,6 +552,34 @@ export const UseTaskInstanceServiceGetExternalLogUrlKeyFn = ({ dagId, dagRunId,
taskId: string;
tryNumber: number;
}, queryKey?: Array<unknown>) => [useTaskInstanceServiceGetExternalLogUrlKey, ...(queryKey ?? [{ dagId, dagRunId, mapIndex, taskId, tryNumber }])];
+export type TaskInstanceServiceGetHitlDetailDefaultResponse = Awaited<ReturnType<typeof TaskInstanceService.getHitlDetail>>;
+export type TaskInstanceServiceGetHitlDetailQueryResult<TData = TaskInstanceServiceGetHitlDetailDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
+export const useTaskInstanceServiceGetHitlDetailKey = "TaskInstanceServiceGetHitlDetail";
+export const UseTaskInstanceServiceGetHitlDetailKeyFn = ({ dagId, dagRunId, mapIndex, taskId }: {
+ dagId: string;
+ dagRunId: string;
+ mapIndex: number;
+ taskId: string;
+}, queryKey?: Array<unknown>) => [useTaskInstanceServiceGetHitlDetailKey, ...(queryKey ?? [{ dagId, dagRunId, mapIndex, taskId }])];
+export type TaskInstanceServiceGetHitlDetailsDefaultResponse = Awaited<ReturnType<typeof TaskInstanceService.getHitlDetails>>;
+export type TaskInstanceServiceGetHitlDetailsQueryResult<TData = TaskInstanceServiceGetHitlDetailsDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
+export const useTaskInstanceServiceGetHitlDetailsKey = "TaskInstanceServiceGetHitlDetails";
+export const UseTaskInstanceServiceGetHitlDetailsKeyFn = ({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
+ bodySearch?: string;
+ dagId: string;
+ dagIdPattern?: string;
+ dagRunId: string;
+ limit?: number;
+ offset?: number;
+ orderBy?: string[];
+ respondedByUserId?: string[];
+ respondedByUserName?: string[];
+ responseReceived?: boolean;
+ state?: string[];
+ subjectSearch?: string;
+ taskId?: string;
+ taskIdPattern?: string;
+}, queryKey?: Array<unknown>) => [useTaskInstanceServiceGetHitlDetailsKey, ...(queryKey ?? [{ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }])];
export type ImportErrorServiceGetImportErrorDefaultResponse = Awaited<ReturnType<typeof ImportErrorService.getImportError>>;
export type ImportErrorServiceGetImportErrorQueryResult<TData = ImportErrorServiceGetImportErrorDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
export const useImportErrorServiceGetImportErrorKey = "ImportErrorServiceGetImportError";
@@ -705,34 +733,6 @@ export const UseDagVersionServiceGetDagVersionsKeyFn = ({ bundleName, bundleVers
orderBy?: string[];
versionNumber?: number;
}, queryKey?: Array<unknown>) => [useDagVersionServiceGetDagVersionsKey, ...(queryKey ?? [{ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }])];
-export type HumanInTheLoopServiceGetHitlDetailDefaultResponse = Awaited<ReturnType<typeof HumanInTheLoopService.getHitlDetail>>;
-export type HumanInTheLoopServiceGetHitlDetailQueryResult<TData = HumanInTheLoopServiceGetHitlDetailDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
-export const useHumanInTheLoopServiceGetHitlDetailKey = "HumanInTheLoopServiceGetHitlDetail";
-export const UseHumanInTheLoopServiceGetHitlDetailKeyFn = ({ dagId, dagRunId, mapIndex, taskId }: {
- dagId: string;
- dagRunId: string;
- mapIndex?: number;
- taskId: string;
-}, queryKey?: Array<unknown>) => [useHumanInTheLoopServiceGetHitlDetailKey, ...(queryKey ?? [{ dagId, dagRunId, mapIndex, taskId }])];
-export type HumanInTheLoopServiceGetHitlDetailsDefaultResponse = Awaited<ReturnType<typeof HumanInTheLoopService.getHitlDetails>>;
-export type HumanInTheLoopServiceGetHitlDetailsQueryResult<TData = HumanInTheLoopServiceGetHitlDetailsDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
-export const useHumanInTheLoopServiceGetHitlDetailsKey = "HumanInTheLoopServiceGetHitlDetails";
-export const UseHumanInTheLoopServiceGetHitlDetailsKeyFn = ({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
- bodySearch?: string;
- dagId?: string;
- dagIdPattern?: string;
- dagRunId?: string;
- limit?: number;
- offset?: number;
- orderBy?: string[];
- respondedByUserId?: string[];
- respondedByUserName?: string[];
- responseReceived?: boolean;
- state?: string[];
- subjectSearch?: string;
- taskId?: string;
- taskIdPattern?: string;
-} = {}, queryKey?: Array<unknown>) => [useHumanInTheLoopServiceGetHitlDetailsKey, ...(queryKey ?? [{ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }])];
export type MonitorServiceGetHealthDefaultResponse = Awaited<ReturnType<typeof MonitorService.getHealth>>;
export type MonitorServiceGetHealthQueryResult<TData = MonitorServiceGetHealthDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
export const useMonitorServiceGetHealthKey = "MonitorServiceGetHealth";
@@ -870,12 +870,12 @@ export type TaskInstanceServicePatchTaskInstanceByMapIndexMutationResult = Await
export type TaskInstanceServiceBulkTaskInstancesMutationResult = Awaited<ReturnType<typeof TaskInstanceService.bulkTaskInstances>>;
export type TaskInstanceServicePatchTaskInstanceDryRunByMapIndexMutationResult = Awaited<ReturnType<typeof TaskInstanceService.patchTaskInstanceDryRunByMapIndex>>;
export type TaskInstanceServicePatchTaskInstanceDryRunMutationResult = Awaited<ReturnType<typeof TaskInstanceService.patchTaskInstanceDryRun>>;
+export type TaskInstanceServiceUpdateHitlDetailMutationResult = Awaited<ReturnType<typeof TaskInstanceService.updateHitlDetail>>;
export type PoolServicePatchPoolMutationResult = Awaited<ReturnType<typeof PoolService.patchPool>>;
export type PoolServiceBulkPoolsMutationResult = Awaited<ReturnType<typeof PoolService.bulkPools>>;
export type XcomServiceUpdateXcomEntryMutationResult = Awaited<ReturnType<typeof XcomService.updateXcomEntry>>;
export type VariableServicePatchVariableMutationResult = Awaited<ReturnType<typeof VariableService.patchVariable>>;
export type VariableServiceBulkVariablesMutationResult = Awaited<ReturnType<typeof VariableService.bulkVariables>>;
-export type HumanInTheLoopServiceUpdateHitlDetailMutationResult = Awaited<ReturnType<typeof HumanInTheLoopService.updateHitlDetail>>;
export type AssetServiceDeleteAssetQueuedEventsMutationResult = Awaited<ReturnType<typeof AssetService.deleteAssetQueuedEvents>>;
export type AssetServiceDeleteDagAssetQueuedEventsMutationResult = Awaited<ReturnType<typeof AssetService.deleteDagAssetQueuedEvents>>;
export type AssetServiceDeleteDagAssetQueuedEventMutationResult = Awaited<ReturnType<typeof AssetService.deleteDagAssetQueuedEvent>>;
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
index da76a35a8ce..bad321b274c 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
@@ -1,7 +1,7 @@
// generated with @7nohe/openapi-react-query-codegen@1.6.2
import { type QueryClient } from "@tanstack/react-query";
-import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, HumanInTheLoopService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, StructureService, TaskInst [...]
+import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, StructureService, TaskInstanceService, TaskServic [...]
import { DagRunState, DagWarningType } from "../requests/types.gen";
import * as Common from "./common";
/**
@@ -1049,6 +1049,60 @@ export const ensureUseTaskInstanceServiceGetExternalLogUrlData = (queryClient: Q
tryNumber: number;
}) => queryClient.ensureQueryData({ queryKey: Common.UseTaskInstanceServiceGetExternalLogUrlKeyFn({ dagId, dagRunId, mapIndex, taskId, tryNumber }), queryFn: () => TaskInstanceService.getExternalLogUrl({ dagId, dagRunId, mapIndex, taskId, tryNumber }) });
/**
+* Get Hitl Detail
+* Get a Human-in-the-loop detail of a specific task instance.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.dagRunId
+* @param data.taskId
+* @param data.mapIndex
+* @returns HITLDetail Successful Response
+* @throws ApiError
+*/
+export const ensureUseTaskInstanceServiceGetHitlDetailData = (queryClient: QueryClient, { dagId, dagRunId, mapIndex, taskId }: {
+ dagId: string;
+ dagRunId: string;
+ mapIndex: number;
+ taskId: string;
+}) => queryClient.ensureQueryData({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailKeyFn({ dagId, dagRunId, mapIndex, taskId }), queryFn: () => TaskInstanceService.getHitlDetail({ dagId, dagRunId, mapIndex, taskId }) });
+/**
+* Get Hitl Details
+* Get Human-in-the-loop details.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.dagRunId
+* @param data.limit
+* @param data.offset
+* @param data.orderBy
+* @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.taskId
+* @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.state
+* @param data.responseReceived
+* @param data.respondedByUserId
+* @param data.respondedByUserName
+* @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @returns HITLDetailCollection Successful Response
+* @throws ApiError
+*/
+export const ensureUseTaskInstanceServiceGetHitlDetailsData = (queryClient: QueryClient, { bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
+ bodySearch?: string;
+ dagId: string;
+ dagIdPattern?: string;
+ dagRunId: string;
+ limit?: number;
+ offset?: number;
+ orderBy?: string[];
+ respondedByUserId?: string[];
+ respondedByUserName?: string[];
+ responseReceived?: boolean;
+ state?: string[];
+ subjectSearch?: string;
+ taskId?: string;
+ taskIdPattern?: string;
+}) => queryClient.ensureQueryData({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) });
+/**
* Get Import Error
* Get an import error.
* @param data The data for the request.
@@ -1341,60 +1395,6 @@ export const ensureUseDagVersionServiceGetDagVersionsData = (queryClient: QueryC
versionNumber?: number;
}) => queryClient.ensureQueryData({ queryKey: Common.UseDagVersionServiceGetDagVersionsKeyFn({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }), queryFn: () => DagVersionService.getDagVersions({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }) });
/**
-* Get Hitl Detail
-* Get a Human-in-the-loop detail of a specific task instance.
-* @param data The data for the request.
-* @param data.dagId
-* @param data.dagRunId
-* @param data.taskId
-* @param data.mapIndex
-* @returns HITLDetail Successful Response
-* @throws ApiError
-*/
-export const ensureUseHumanInTheLoopServiceGetHitlDetailData = (queryClient: QueryClient, { dagId, dagRunId, mapIndex, taskId }: {
- dagId: string;
- dagRunId: string;
- mapIndex?: number;
- taskId: string;
-}) => queryClient.ensureQueryData({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailKeyFn({ dagId, dagRunId, mapIndex, taskId }), queryFn: () => HumanInTheLoopService.getHitlDetail({ dagId, dagRunId, mapIndex, taskId }) });
-/**
-* Get Hitl Details
-* Get Human-in-the-loop details.
-* @param data The data for the request.
-* @param data.limit
-* @param data.offset
-* @param data.orderBy
-* @param data.dagId
-* @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.dagRunId
-* @param data.taskId
-* @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.state
-* @param data.responseReceived
-* @param data.respondedByUserId
-* @param data.respondedByUserName
-* @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @returns HITLDetailCollection Successful Response
-* @throws ApiError
-*/
-export const ensureUseHumanInTheLoopServiceGetHitlDetailsData = (queryClient: QueryClient, { bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
- bodySearch?: string;
- dagId?: string;
- dagIdPattern?: string;
- dagRunId?: string;
- limit?: number;
- offset?: number;
- orderBy?: string[];
- respondedByUserId?: string[];
- respondedByUserName?: string[];
- responseReceived?: boolean;
- state?: string[];
- subjectSearch?: string;
- taskId?: string;
- taskIdPattern?: string;
-} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskId [...]
-/**
* Get Health
* @returns HealthInfoResponse Successful Response
* @throws ApiError
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
index af773c94bdd..0f3565e9fe0 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -1,7 +1,7 @@
// generated with @7nohe/openapi-react-query-codegen@1.6.2
import { type QueryClient } from "@tanstack/react-query";
-import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, HumanInTheLoopService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, StructureService, TaskInst [...]
+import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, StructureService, TaskInstanceService, TaskServic [...]
import { DagRunState, DagWarningType } from "../requests/types.gen";
import * as Common from "./common";
/**
@@ -1049,6 +1049,60 @@ export const prefetchUseTaskInstanceServiceGetExternalLogUrl = (queryClient: Que
tryNumber: number;
}) => queryClient.prefetchQuery({ queryKey: Common.UseTaskInstanceServiceGetExternalLogUrlKeyFn({ dagId, dagRunId, mapIndex, taskId, tryNumber }), queryFn: () => TaskInstanceService.getExternalLogUrl({ dagId, dagRunId, mapIndex, taskId, tryNumber }) });
/**
+* Get Hitl Detail
+* Get a Human-in-the-loop detail of a specific task instance.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.dagRunId
+* @param data.taskId
+* @param data.mapIndex
+* @returns HITLDetail Successful Response
+* @throws ApiError
+*/
+export const prefetchUseTaskInstanceServiceGetHitlDetail = (queryClient: QueryClient, { dagId, dagRunId, mapIndex, taskId }: {
+ dagId: string;
+ dagRunId: string;
+ mapIndex: number;
+ taskId: string;
+}) => queryClient.prefetchQuery({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailKeyFn({ dagId, dagRunId, mapIndex, taskId }), queryFn: () => TaskInstanceService.getHitlDetail({ dagId, dagRunId, mapIndex, taskId }) });
+/**
+* Get Hitl Details
+* Get Human-in-the-loop details.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.dagRunId
+* @param data.limit
+* @param data.offset
+* @param data.orderBy
+* @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.taskId
+* @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.state
+* @param data.responseReceived
+* @param data.respondedByUserId
+* @param data.respondedByUserName
+* @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @returns HITLDetailCollection Successful Response
+* @throws ApiError
+*/
+export const prefetchUseTaskInstanceServiceGetHitlDetails = (queryClient: QueryClient, { bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
+ bodySearch?: string;
+ dagId: string;
+ dagIdPattern?: string;
+ dagRunId: string;
+ limit?: number;
+ offset?: number;
+ orderBy?: string[];
+ respondedByUserId?: string[];
+ respondedByUserName?: string[];
+ responseReceived?: boolean;
+ state?: string[];
+ subjectSearch?: string;
+ taskId?: string;
+ taskIdPattern?: string;
+}) => queryClient.prefetchQuery({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }) });
+/**
* Get Import Error
* Get an import error.
* @param data The data for the request.
@@ -1341,60 +1395,6 @@ export const prefetchUseDagVersionServiceGetDagVersions = (queryClient: QueryCli
versionNumber?: number;
}) => queryClient.prefetchQuery({ queryKey: Common.UseDagVersionServiceGetDagVersionsKeyFn({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }), queryFn: () => DagVersionService.getDagVersions({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }) });
/**
-* Get Hitl Detail
-* Get a Human-in-the-loop detail of a specific task instance.
-* @param data The data for the request.
-* @param data.dagId
-* @param data.dagRunId
-* @param data.taskId
-* @param data.mapIndex
-* @returns HITLDetail Successful Response
-* @throws ApiError
-*/
-export const prefetchUseHumanInTheLoopServiceGetHitlDetail = (queryClient: QueryClient, { dagId, dagRunId, mapIndex, taskId }: {
- dagId: string;
- dagRunId: string;
- mapIndex?: number;
- taskId: string;
-}) => queryClient.prefetchQuery({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailKeyFn({ dagId, dagRunId, mapIndex, taskId }), queryFn: () => HumanInTheLoopService.getHitlDetail({ dagId, dagRunId, mapIndex, taskId }) });
-/**
-* Get Hitl Details
-* Get Human-in-the-loop details.
-* @param data The data for the request.
-* @param data.limit
-* @param data.offset
-* @param data.orderBy
-* @param data.dagId
-* @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.dagRunId
-* @param data.taskId
-* @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.state
-* @param data.responseReceived
-* @param data.respondedByUserId
-* @param data.respondedByUserName
-* @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @returns HITLDetailCollection Successful Response
-* @throws ApiError
-*/
-export const prefetchUseHumanInTheLoopServiceGetHitlDetails = (queryClient: QueryClient, { bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
- bodySearch?: string;
- dagId?: string;
- dagIdPattern?: string;
- dagRunId?: string;
- limit?: number;
- offset?: number;
- orderBy?: string[];
- respondedByUserId?: string[];
- respondedByUserName?: string[];
- responseReceived?: boolean;
- state?: string[];
- subjectSearch?: string;
- taskId?: string;
- taskIdPattern?: string;
-} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPa [...]
-/**
* Get Health
* @returns HealthInfoResponse Successful Response
* @throws ApiError
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
index 6c70c69ac5c..9d23ddbcfe6 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
@@ -1,7 +1,7 @@
// generated with @7nohe/openapi-react-query-codegen@1.6.2
import { UseMutationOptions, UseQueryOptions, useMutation, useQuery } from "@tanstack/react-query";
-import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagParsingService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, HumanInTheLoopService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, Structu [...]
+import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagParsingService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, StructureService, TaskInstance [...]
import { BackfillPostBody, BulkBody_BulkTaskInstanceBody_, BulkBody_ConnectionBody_, BulkBody_PoolBody_, BulkBody_VariableBody_, ClearTaskInstancesBody, ConnectionBody, CreateAssetEventsBody, DAGPatchBody, DAGRunClearBody, DAGRunPatchBody, DAGRunsBatchBody, DagRunState, DagWarningType, PatchTaskInstanceBody, PoolBody, PoolPatchBody, TaskInstancesBatchBody, TriggerDAGRunPostBody, UpdateHITLDetailPayload, VariableBody, XComCreateBody, XComUpdateBody } from "../requests/types.gen";
import * as Common from "./common";
/**
@@ -1049,6 +1049,60 @@ export const useTaskInstanceServiceGetExternalLogUrl = <TData = Common.TaskInsta
tryNumber: number;
}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseTaskInstanceServiceGetExternalLogUrlKeyFn({ dagId, dagRunId, mapIndex, taskId, tryNumber }, queryKey), queryFn: () => TaskInstanceService.getExternalLogUrl({ dagId, dagRunId, mapIndex, taskId, tryNumber }) as TData, ...options });
/**
+* Get Hitl Detail
+* Get a Human-in-the-loop detail of a specific task instance.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.dagRunId
+* @param data.taskId
+* @param data.mapIndex
+* @returns HITLDetail Successful Response
+* @throws ApiError
+*/
+export const useTaskInstanceServiceGetHitlDetail = <TData = Common.TaskInstanceServiceGetHitlDetailDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ dagId, dagRunId, mapIndex, taskId }: {
+ dagId: string;
+ dagRunId: string;
+ mapIndex: number;
+ taskId: string;
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailKeyFn({ dagId, dagRunId, mapIndex, taskId }, queryKey), queryFn: () => TaskInstanceService.getHitlDetail({ dagId, dagRunId, mapIndex, taskId }) as TData, ...options });
+/**
+* Get Hitl Details
+* Get Human-in-the-loop details.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.dagRunId
+* @param data.limit
+* @param data.offset
+* @param data.orderBy
+* @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.taskId
+* @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.state
+* @param data.responseReceived
+* @param data.respondedByUserId
+* @param data.respondedByUserName
+* @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @returns HITLDetailCollection Successful Response
+* @throws ApiError
+*/
+export const useTaskInstanceServiceGetHitlDetails = <TData = Common.TaskInstanceServiceGetHitlDetailsDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
+ bodySearch?: string;
+ dagId: string;
+ dagIdPattern?: string;
+ dagRunId: string;
+ limit?: number;
+ offset?: number;
+ orderBy?: string[];
+ respondedByUserId?: string[];
+ respondedByUserName?: string[];
+ responseReceived?: boolean;
+ state?: string[];
+ subjectSearch?: string;
+ taskId?: string;
+ taskIdPattern?: string;
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, res [...]
+/**
* Get Import Error
* Get an import error.
* @param data The data for the request.
@@ -1341,60 +1395,6 @@ export const useDagVersionServiceGetDagVersions = <TData = Common.DagVersionServ
versionNumber?: number;
}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseDagVersionServiceGetDagVersionsKeyFn({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }, queryKey), queryFn: () => DagVersionService.getDagVersions({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }) as TData, ...options });
/**
-* Get Hitl Detail
-* Get a Human-in-the-loop detail of a specific task instance.
-* @param data The data for the request.
-* @param data.dagId
-* @param data.dagRunId
-* @param data.taskId
-* @param data.mapIndex
-* @returns HITLDetail Successful Response
-* @throws ApiError
-*/
-export const useHumanInTheLoopServiceGetHitlDetail = <TData = Common.HumanInTheLoopServiceGetHitlDetailDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ dagId, dagRunId, mapIndex, taskId }: {
- dagId: string;
- dagRunId: string;
- mapIndex?: number;
- taskId: string;
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailKeyFn({ dagId, dagRunId, mapIndex, taskId }, queryKey), queryFn: () => HumanInTheLoopService.getHitlDetail({ dagId, dagRunId, mapIndex, taskId }) as TData, ...options });
-/**
-* Get Hitl Details
-* Get Human-in-the-loop details.
-* @param data The data for the request.
-* @param data.limit
-* @param data.offset
-* @param data.orderBy
-* @param data.dagId
-* @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.dagRunId
-* @param data.taskId
-* @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.state
-* @param data.responseReceived
-* @param data.respondedByUserId
-* @param data.respondedByUserName
-* @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @returns HITLDetailCollection Successful Response
-* @throws ApiError
-*/
-export const useHumanInTheLoopServiceGetHitlDetails = <TData = Common.HumanInTheLoopServiceGetHitlDetailsDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
- bodySearch?: string;
- dagId?: string;
- dagIdPattern?: string;
- dagRunId?: string;
- limit?: number;
- offset?: number;
- orderBy?: string[];
- respondedByUserId?: string[];
- respondedByUserName?: string[];
- responseReceived?: boolean;
- state?: string[];
- subjectSearch?: string;
- taskId?: string;
- taskIdPattern?: string;
-} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, ord [...]
-/**
* Get Health
* @returns HealthInfoResponse Successful Response
* @throws ApiError
@@ -2141,6 +2141,31 @@ export const useTaskInstanceServicePatchTaskInstanceDryRun = <TData = Common.Tas
updateMask?: string[];
}, TContext>({ mutationFn: ({ dagId, dagRunId, mapIndex, requestBody, taskId, updateMask }) => TaskInstanceService.patchTaskInstanceDryRun({ dagId, dagRunId, mapIndex, requestBody, taskId, updateMask }) as unknown as Promise<TData>, ...options });
/**
+* Update Hitl Detail
+* Update a Human-in-the-loop detail.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.dagRunId
+* @param data.taskId
+* @param data.mapIndex
+* @param data.requestBody
+* @returns HITLDetailResponse Successful Response
+* @throws ApiError
+*/
+export const useTaskInstanceServiceUpdateHitlDetail = <TData = Common.TaskInstanceServiceUpdateHitlDetailMutationResult, TError = unknown, TContext = unknown>(options?: Omit<UseMutationOptions<TData, TError, {
+ dagId: string;
+ dagRunId: string;
+ mapIndex: number;
+ requestBody: UpdateHITLDetailPayload;
+ taskId: string;
+}, TContext>, "mutationFn">) => useMutation<TData, TError, {
+ dagId: string;
+ dagRunId: string;
+ mapIndex: number;
+ requestBody: UpdateHITLDetailPayload;
+ taskId: string;
+}, TContext>({ mutationFn: ({ dagId, dagRunId, mapIndex, requestBody, taskId }) => TaskInstanceService.updateHitlDetail({ dagId, dagRunId, mapIndex, requestBody, taskId }) as unknown as Promise<TData>, ...options });
+/**
* Patch Pool
* Update a Pool.
* @param data The data for the request.
@@ -2230,31 +2255,6 @@ export const useVariableServiceBulkVariables = <TData = Common.VariableServiceBu
requestBody: BulkBody_VariableBody_;
}, TContext>({ mutationFn: ({ requestBody }) => VariableService.bulkVariables({ requestBody }) as unknown as Promise<TData>, ...options });
/**
-* Update Hitl Detail
-* Update a Human-in-the-loop detail.
-* @param data The data for the request.
-* @param data.dagId
-* @param data.dagRunId
-* @param data.taskId
-* @param data.requestBody
-* @param data.mapIndex
-* @returns HITLDetailResponse Successful Response
-* @throws ApiError
-*/
-export const useHumanInTheLoopServiceUpdateHitlDetail = <TData = Common.HumanInTheLoopServiceUpdateHitlDetailMutationResult, TError = unknown, TContext = unknown>(options?: Omit<UseMutationOptions<TData, TError, {
- dagId: string;
- dagRunId: string;
- mapIndex?: number;
- requestBody: UpdateHITLDetailPayload;
- taskId: string;
-}, TContext>, "mutationFn">) => useMutation<TData, TError, {
- dagId: string;
- dagRunId: string;
- mapIndex?: number;
- requestBody: UpdateHITLDetailPayload;
- taskId: string;
-}, TContext>({ mutationFn: ({ dagId, dagRunId, mapIndex, requestBody, taskId }) => HumanInTheLoopService.updateHitlDetail({ dagId, dagRunId, mapIndex, requestBody, taskId }) as unknown as Promise<TData>, ...options });
-/**
* Delete Asset Queued Events
* Delete queued asset events for an asset.
* @param data The data for the request.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
index 79a5f974e07..4d5fea56dac 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
@@ -1,7 +1,7 @@
// generated with @7nohe/openapi-react-query-codegen@1.6.2
import { UseQueryOptions, useSuspenseQuery } from "@tanstack/react-query";
-import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, HumanInTheLoopService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, StructureService, TaskInst [...]
+import { AssetService, AuthLinksService, BackfillService, CalendarService, ConfigService, ConnectionService, DagReportService, DagRunService, DagService, DagSourceService, DagStatsService, DagVersionService, DagWarningService, DashboardService, DependenciesService, EventLogService, ExperimentalService, ExtraLinksService, GridService, ImportErrorService, JobService, LoginService, MonitorService, PluginService, PoolService, ProviderService, StructureService, TaskInstanceService, TaskServic [...]
import { DagRunState, DagWarningType } from "../requests/types.gen";
import * as Common from "./common";
/**
@@ -1049,6 +1049,60 @@ export const useTaskInstanceServiceGetExternalLogUrlSuspense = <TData = Common.T
tryNumber: number;
}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseTaskInstanceServiceGetExternalLogUrlKeyFn({ dagId, dagRunId, mapIndex, taskId, tryNumber }, queryKey), queryFn: () => TaskInstanceService.getExternalLogUrl({ dagId, dagRunId, mapIndex, taskId, tryNumber }) as TData, ...options });
/**
+* Get Hitl Detail
+* Get a Human-in-the-loop detail of a specific task instance.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.dagRunId
+* @param data.taskId
+* @param data.mapIndex
+* @returns HITLDetail Successful Response
+* @throws ApiError
+*/
+export const useTaskInstanceServiceGetHitlDetailSuspense = <TData = Common.TaskInstanceServiceGetHitlDetailDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ dagId, dagRunId, mapIndex, taskId }: {
+ dagId: string;
+ dagRunId: string;
+ mapIndex: number;
+ taskId: string;
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailKeyFn({ dagId, dagRunId, mapIndex, taskId }, queryKey), queryFn: () => TaskInstanceService.getHitlDetail({ dagId, dagRunId, mapIndex, taskId }) as TData, ...options });
+/**
+* Get Hitl Details
+* Get Human-in-the-loop details.
+* @param data The data for the request.
+* @param data.dagId
+* @param data.dagRunId
+* @param data.limit
+* @param data.offset
+* @param data.orderBy
+* @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.taskId
+* @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.state
+* @param data.responseReceived
+* @param data.respondedByUserId
+* @param data.respondedByUserName
+* @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+* @returns HITLDetailCollection Successful Response
+* @throws ApiError
+*/
+export const useTaskInstanceServiceGetHitlDetailsSuspense = <TData = Common.TaskInstanceServiceGetHitlDetailsDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
+ bodySearch?: string;
+ dagId: string;
+ dagIdPattern?: string;
+ dagRunId: string;
+ limit?: number;
+ offset?: number;
+ orderBy?: string[];
+ respondedByUserId?: string[];
+ respondedByUserName?: string[];
+ responseReceived?: boolean;
+ state?: string[];
+ subjectSearch?: string;
+ taskId?: string;
+ taskIdPattern?: string;
+}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseTaskInstanceServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => TaskInstanceService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orde [...]
+/**
* Get Import Error
* Get an import error.
* @param data The data for the request.
@@ -1341,60 +1395,6 @@ export const useDagVersionServiceGetDagVersionsSuspense = <TData = Common.DagVer
versionNumber?: number;
}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseDagVersionServiceGetDagVersionsKeyFn({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }, queryKey), queryFn: () => DagVersionService.getDagVersions({ bundleName, bundleVersion, dagId, limit, offset, orderBy, versionNumber }) as TData, ...options });
/**
-* Get Hitl Detail
-* Get a Human-in-the-loop detail of a specific task instance.
-* @param data The data for the request.
-* @param data.dagId
-* @param data.dagRunId
-* @param data.taskId
-* @param data.mapIndex
-* @returns HITLDetail Successful Response
-* @throws ApiError
-*/
-export const useHumanInTheLoopServiceGetHitlDetailSuspense = <TData = Common.HumanInTheLoopServiceGetHitlDetailDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ dagId, dagRunId, mapIndex, taskId }: {
- dagId: string;
- dagRunId: string;
- mapIndex?: number;
- taskId: string;
-}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailKeyFn({ dagId, dagRunId, mapIndex, taskId }, queryKey), queryFn: () => HumanInTheLoopService.getHitlDetail({ dagId, dagRunId, mapIndex, taskId }) as TData, ...options });
-/**
-* Get Hitl Details
-* Get Human-in-the-loop details.
-* @param data The data for the request.
-* @param data.limit
-* @param data.offset
-* @param data.orderBy
-* @param data.dagId
-* @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.dagRunId
-* @param data.taskId
-* @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.state
-* @param data.responseReceived
-* @param data.respondedByUserId
-* @param data.respondedByUserName
-* @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
-* @returns HITLDetailCollection Successful Response
-* @throws ApiError
-*/
-export const useHumanInTheLoopServiceGetHitlDetailsSuspense = <TData = Common.HumanInTheLoopServiceGetHitlDetailsDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }: {
- bodySearch?: string;
- dagId?: string;
- dagIdPattern?: string;
- dagRunId?: string;
- limit?: number;
- offset?: number;
- orderBy?: string[];
- respondedByUserId?: string[];
- respondedByUserName?: string[];
- responseReceived?: boolean;
- state?: string[];
- subjectSearch?: string;
- taskId?: string;
- taskIdPattern?: string;
-} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseHumanInTheLoopServiceGetHitlDetailsKeyFn({ bodySearch, dagId, dagIdPattern, dagRunId, limit, offset, orderBy, respondedByUserId, respondedByUserName, responseReceived, state, subjectSearch, taskId, taskIdPattern }, queryKey), queryFn: () => HumanInTheLoopService.getHitlDetails({ bodySearch, dagId, dagIdPattern, dagRunId, limit, off [...]
-/**
* Get Health
* @returns HealthInfoResponse Successful Response
* @throws ApiError
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
index ed570c2fc9d..468bea4460d 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
@@ -3,7 +3,7 @@
import type { CancelablePromise } from './core/CancelablePromise';
import { OpenAPI } from './core/OpenAPI';
import { request as __request } from './core/request';
-import type { GetAssetsData, GetAssetsResponse, GetAssetAliasesData, GetAssetAliasesResponse, GetAssetAliasData, GetAssetAliasResponse, GetAssetEventsData, GetAssetEventsResponse, CreateAssetEventData, CreateAssetEventResponse, MaterializeAssetData, MaterializeAssetResponse, GetAssetQueuedEventsData, GetAssetQueuedEventsResponse, DeleteAssetQueuedEventsData, DeleteAssetQueuedEventsResponse, GetAssetData, GetAssetResponse, GetDagAssetQueuedEventsData, GetDagAssetQueuedEventsResponse, Dele [...]
+import type { GetAssetsData, GetAssetsResponse, GetAssetAliasesData, GetAssetAliasesResponse, GetAssetAliasData, GetAssetAliasResponse, GetAssetEventsData, GetAssetEventsResponse, CreateAssetEventData, CreateAssetEventResponse, MaterializeAssetData, MaterializeAssetResponse, GetAssetQueuedEventsData, GetAssetQueuedEventsResponse, DeleteAssetQueuedEventsData, DeleteAssetQueuedEventsResponse, GetAssetData, GetAssetResponse, GetDagAssetQueuedEventsData, GetDagAssetQueuedEventsResponse, Dele [...]
export class AssetService {
/**
@@ -2710,6 +2710,121 @@ export class TaskInstanceService {
});
}
+ /**
+ * Update Hitl Detail
+ * Update a Human-in-the-loop detail.
+ * @param data The data for the request.
+ * @param data.dagId
+ * @param data.dagRunId
+ * @param data.taskId
+ * @param data.mapIndex
+ * @param data.requestBody
+ * @returns HITLDetailResponse Successful Response
+ * @throws ApiError
+ */
+ public static updateHitlDetail(data: UpdateHitlDetailData): CancelablePromise<UpdateHitlDetailResponse> {
+ return __request(OpenAPI, {
+ method: 'PATCH',
+ url: '/api/v2/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/{map_index}/hitlDetails',
+ path: {
+ dag_id: data.dagId,
+ dag_run_id: data.dagRunId,
+ task_id: data.taskId,
+ map_index: data.mapIndex
+ },
+ body: data.requestBody,
+ mediaType: 'application/json',
+ errors: {
+ 401: 'Unauthorized',
+ 403: 'Forbidden',
+ 404: 'Not Found',
+ 409: 'Conflict',
+ 422: 'Validation Error'
+ }
+ });
+ }
+
+ /**
+ * Get Hitl Detail
+ * Get a Human-in-the-loop detail of a specific task instance.
+ * @param data The data for the request.
+ * @param data.dagId
+ * @param data.dagRunId
+ * @param data.taskId
+ * @param data.mapIndex
+ * @returns HITLDetail Successful Response
+ * @throws ApiError
+ */
+ public static getHitlDetail(data: GetHitlDetailData): CancelablePromise<GetHitlDetailResponse> {
+ return __request(OpenAPI, {
+ method: 'GET',
+ url: '/api/v2/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/{map_index}/hitlDetails',
+ path: {
+ dag_id: data.dagId,
+ dag_run_id: data.dagRunId,
+ task_id: data.taskId,
+ map_index: data.mapIndex
+ },
+ errors: {
+ 401: 'Unauthorized',
+ 403: 'Forbidden',
+ 404: 'Not Found',
+ 422: 'Validation Error'
+ }
+ });
+ }
+
+ /**
+ * Get Hitl Details
+ * Get Human-in-the-loop details.
+ * @param data The data for the request.
+ * @param data.dagId
+ * @param data.dagRunId
+ * @param data.limit
+ * @param data.offset
+ * @param data.orderBy
+ * @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+ * @param data.taskId
+ * @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+ * @param data.state
+ * @param data.responseReceived
+ * @param data.respondedByUserId
+ * @param data.respondedByUserName
+ * @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+ * @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+ * @returns HITLDetailCollection Successful Response
+ * @throws ApiError
+ */
+ public static getHitlDetails(data: GetHitlDetailsData): CancelablePromise<GetHitlDetailsResponse> {
+ return __request(OpenAPI, {
+ method: 'GET',
+ url: '/api/v2/dags/{dag_id}/dagRuns/{dag_run_id}/hitlDetails',
+ path: {
+ dag_id: data.dagId,
+ dag_run_id: data.dagRunId
+ },
+ query: {
+ limit: data.limit,
+ offset: data.offset,
+ order_by: data.orderBy,
+ dag_id_pattern: data.dagIdPattern,
+ task_id: data.taskId,
+ task_id_pattern: data.taskIdPattern,
+ state: data.state,
+ response_received: data.responseReceived,
+ responded_by_user_id: data.respondedByUserId,
+ responded_by_user_name: data.respondedByUserName,
+ subject_search: data.subjectSearch,
+ body_search: data.bodySearch
+ },
+ errors: {
+ 401: 'Unauthorized',
+ 403: 'Forbidden',
+ 422: 'Validation Error'
+ }
+ });
+ }
+
}
export class ImportErrorService {
@@ -3540,126 +3655,6 @@ export class DagVersionService {
}
-export class HumanInTheLoopService {
- /**
- * Update Hitl Detail
- * Update a Human-in-the-loop detail.
- * @param data The data for the request.
- * @param data.dagId
- * @param data.dagRunId
- * @param data.taskId
- * @param data.requestBody
- * @param data.mapIndex
- * @returns HITLDetailResponse Successful Response
- * @throws ApiError
- */
- public static updateHitlDetail(data: UpdateHitlDetailData): CancelablePromise<UpdateHitlDetailResponse> {
- return __request(OpenAPI, {
- method: 'PATCH',
- url: '/api/v2/hitlDetails/{dag_id}/{dag_run_id}/{task_id}',
- path: {
- dag_id: data.dagId,
- dag_run_id: data.dagRunId,
- task_id: data.taskId
- },
- query: {
- map_index: data.mapIndex
- },
- body: data.requestBody,
- mediaType: 'application/json',
- errors: {
- 401: 'Unauthorized',
- 403: 'Forbidden',
- 404: 'Not Found',
- 409: 'Conflict',
- 422: 'Validation Error'
- }
- });
- }
-
- /**
- * Get Hitl Detail
- * Get a Human-in-the-loop detail of a specific task instance.
- * @param data The data for the request.
- * @param data.dagId
- * @param data.dagRunId
- * @param data.taskId
- * @param data.mapIndex
- * @returns HITLDetail Successful Response
- * @throws ApiError
- */
- public static getHitlDetail(data: GetHitlDetailData): CancelablePromise<GetHitlDetailResponse> {
- return __request(OpenAPI, {
- method: 'GET',
- url: '/api/v2/hitlDetails/{dag_id}/{dag_run_id}/{task_id}',
- path: {
- dag_id: data.dagId,
- dag_run_id: data.dagRunId,
- task_id: data.taskId
- },
- query: {
- map_index: data.mapIndex
- },
- errors: {
- 401: 'Unauthorized',
- 403: 'Forbidden',
- 404: 'Not Found',
- 422: 'Validation Error'
- }
- });
- }
-
- /**
- * Get Hitl Details
- * Get Human-in-the-loop details.
- * @param data The data for the request.
- * @param data.limit
- * @param data.offset
- * @param data.orderBy
- * @param data.dagId
- * @param data.dagIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
- * @param data.dagRunId
- * @param data.taskId
- * @param data.taskIdPattern SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
- * @param data.state
- * @param data.responseReceived
- * @param data.respondedByUserId
- * @param data.respondedByUserName
- * @param data.subjectSearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
- * @param data.bodySearch SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
- * @returns HITLDetailCollection Successful Response
- * @throws ApiError
- */
- public static getHitlDetails(data: GetHitlDetailsData = {}): CancelablePromise<GetHitlDetailsResponse> {
- return __request(OpenAPI, {
- method: 'GET',
- url: '/api/v2/hitlDetails/',
- query: {
- limit: data.limit,
- offset: data.offset,
- order_by: data.orderBy,
- dag_id: data.dagId,
- dag_id_pattern: data.dagIdPattern,
- dag_run_id: data.dagRunId,
- task_id: data.taskId,
- task_id_pattern: data.taskIdPattern,
- state: data.state,
- response_received: data.responseReceived,
- responded_by_user_id: data.respondedByUserId,
- responded_by_user_name: data.respondedByUserName,
- subject_search: data.subjectSearch,
- body_search: data.bodySearch
- },
- errors: {
- 401: 'Unauthorized',
- 403: 'Forbidden',
- 422: 'Validation Error'
- }
- });
- }
-
-}
-
export class MonitorService {
/**
* Get Health
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
index 21a81305bd8..18d40ed2531 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -2827,6 +2827,56 @@ export type GetExternalLogUrlData = {
export type GetExternalLogUrlResponse = ExternalLogUrlResponse;
+export type UpdateHitlDetailData = {
+ dagId: string;
+ dagRunId: string;
+ mapIndex: number;
+ requestBody: UpdateHITLDetailPayload;
+ taskId: string;
+};
+
+export type UpdateHitlDetailResponse = HITLDetailResponse;
+
+export type GetHitlDetailData = {
+ dagId: string;
+ dagRunId: string;
+ mapIndex: number;
+ taskId: string;
+};
+
+export type GetHitlDetailResponse = HITLDetail;
+
+export type GetHitlDetailsData = {
+ /**
+ * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+ */
+ bodySearch?: string | null;
+ dagId: string;
+ /**
+ * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+ */
+ dagIdPattern?: string | null;
+ dagRunId: string;
+ limit?: number;
+ offset?: number;
+ orderBy?: Array<(string)>;
+ respondedByUserId?: Array<(string)>;
+ respondedByUserName?: Array<(string)>;
+ responseReceived?: boolean | null;
+ state?: Array<(string)>;
+ /**
+ * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+ */
+ subjectSearch?: string | null;
+ taskId?: string | null;
+ /**
+ * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
+ */
+ taskIdPattern?: string | null;
+};
+
+export type GetHitlDetailsResponse = HITLDetailCollection;
+
export type GetImportErrorData = {
importErrorId: number;
};
@@ -3073,56 +3123,6 @@ export type GetDagVersionsData = {
export type GetDagVersionsResponse = DAGVersionCollectionResponse;
-export type UpdateHitlDetailData = {
- dagId: string;
- dagRunId: string;
- mapIndex?: number;
- requestBody: UpdateHITLDetailPayload;
- taskId: string;
-};
-
-export type UpdateHitlDetailResponse = HITLDetailResponse;
-
-export type GetHitlDetailData = {
- dagId: string;
- dagRunId: string;
- mapIndex?: number;
- taskId: string;
-};
-
-export type GetHitlDetailResponse = HITLDetail;
-
-export type GetHitlDetailsData = {
- /**
- * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
- */
- bodySearch?: string | null;
- dagId?: string | null;
- /**
- * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
- */
- dagIdPattern?: string | null;
- dagRunId?: string;
- limit?: number;
- offset?: number;
- orderBy?: Array<(string)>;
- respondedByUserId?: Array<(string)>;
- respondedByUserName?: Array<(string)>;
- responseReceived?: boolean | null;
- state?: Array<(string)>;
- /**
- * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
- */
- subjectSearch?: string | null;
- taskId?: string | null;
- /**
- * SQL LIKE expression — use `%` / `_` wildcards (e.g. `%customer_%`). Regular expressions are **not** supported.
- */
- taskIdPattern?: string | null;
-};
-
-export type GetHitlDetailsResponse = HITLDetailCollection;
-
export type GetHealthResponse = HealthInfoResponse;
export type GetVersionResponse = VersionInfo;
@@ -5392,6 +5392,85 @@ export type $OpenApiTs = {
};
};
};
+ '/api/v2/dags/{dag_id}/dagRuns/{dag_run_id}/taskInstances/{task_id}/{map_index}/hitlDetails': {
+ patch: {
+ req: UpdateHitlDetailData;
+ res: {
+ /**
+ * Successful Response
+ */
+ 200: HITLDetailResponse;
+ /**
+ * Unauthorized
+ */
+ 401: HTTPExceptionResponse;
+ /**
+ * Forbidden
+ */
+ 403: HTTPExceptionResponse;
+ /**
+ * Not Found
+ */
+ 404: HTTPExceptionResponse;
+ /**
+ * Conflict
+ */
+ 409: HTTPExceptionResponse;
+ /**
+ * Validation Error
+ */
+ 422: HTTPValidationError;
+ };
+ };
+ get: {
+ req: GetHitlDetailData;
+ res: {
+ /**
+ * Successful Response
+ */
+ 200: HITLDetail;
+ /**
+ * Unauthorized
+ */
+ 401: HTTPExceptionResponse;
+ /**
+ * Forbidden
+ */
+ 403: HTTPExceptionResponse;
+ /**
+ * Not Found
+ */
+ 404: HTTPExceptionResponse;
+ /**
+ * Validation Error
+ */
+ 422: HTTPValidationError;
+ };
+ };
+ };
+ '/api/v2/dags/{dag_id}/dagRuns/{dag_run_id}/hitlDetails': {
+ get: {
+ req: GetHitlDetailsData;
+ res: {
+ /**
+ * Successful Response
+ */
+ 200: HITLDetailCollection;
+ /**
+ * Unauthorized
+ */
+ 401: HTTPExceptionResponse;
+ /**
+ * Forbidden
+ */
+ 403: HTTPExceptionResponse;
+ /**
+ * Validation Error
+ */
+ 422: HTTPValidationError;
+ };
+ };
+ };
'/api/v2/importErrors/{import_error_id}': {
get: {
req: GetImportErrorData;
@@ -6104,85 +6183,6 @@ export type $OpenApiTs = {
};
};
};
- '/api/v2/hitlDetails/{dag_id}/{dag_run_id}/{task_id}': {
- patch: {
- req: UpdateHitlDetailData;
- res: {
- /**
- * Successful Response
- */
- 200: HITLDetailResponse;
- /**
- * Unauthorized
- */
- 401: HTTPExceptionResponse;
- /**
- * Forbidden
- */
- 403: HTTPExceptionResponse;
- /**
- * Not Found
- */
- 404: HTTPExceptionResponse;
- /**
- * Conflict
- */
- 409: HTTPExceptionResponse;
- /**
- * Validation Error
- */
- 422: HTTPValidationError;
- };
- };
- get: {
- req: GetHitlDetailData;
- res: {
- /**
- * Successful Response
- */
- 200: HITLDetail;
- /**
- * Unauthorized
- */
- 401: HTTPExceptionResponse;
- /**
- * Forbidden
- */
- 403: HTTPExceptionResponse;
- /**
- * Not Found
- */
- 404: HTTPExceptionResponse;
- /**
- * Validation Error
- */
- 422: HTTPValidationError;
- };
- };
- };
- '/api/v2/hitlDetails/': {
- get: {
- req: GetHitlDetailsData;
- res: {
- /**
- * Successful Response
- */
- 200: HITLDetailCollection;
- /**
- * Unauthorized
- */
- 401: HTTPExceptionResponse;
- /**
- * Forbidden
- */
- 403: HTTPExceptionResponse;
- /**
- * Validation Error
- */
- 422: HTTPValidationError;
- };
- };
- };
'/api/v2/monitor/health': {
get: {
res: {
diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py
index f29fe60cfef..61f6488d5fc 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_hitl.py
@@ -65,7 +65,7 @@ def sample_ti(
@pytest.fixture
def sample_ti_url_identifier() -> str:
- return f"{DAG_ID}/test/{TASK_ID}"
+ return f"/dags/{DAG_ID}/dagRuns/test/taskInstances/{TASK_ID}/-1"
@pytest.fixture
@@ -269,11 +269,10 @@ def cleanup_audit_log(session: Session) -> None:
session.commit()
-def _assert_sample_audit_log(audit_log: Log, map_index: int | None) -> None:
+def _assert_sample_audit_log(audit_log: Log) -> None:
assert audit_log.dag_id == DAG_ID
assert audit_log.task_id == TASK_ID
assert audit_log.run_id == "test"
- assert audit_log.map_index is None
assert audit_log.try_number is None
assert audit_log.owner == "test"
assert audit_log.owner_display_name == "test"
@@ -286,9 +285,8 @@ def _assert_sample_audit_log(audit_log: Log, map_index: int | None) -> None:
"chosen_options": ["Approve"],
"params_input": {"input_1": 2},
"method": "PATCH",
+ "map_index": "-1",
}
- if map_index is not None:
- expected_extra["map_index"] = str(map_index)
assert json.loads(audit_log.extra) == expected_extra
@@ -301,21 +299,17 @@ def sample_update_payload() -> dict[str, Any]:
class TestUpdateHITLDetailEndpoint:
@time_machine.travel(datetime(2025, 7, 3, 0, 0, 0), tick=False)
@pytest.mark.usefixtures("sample_hitl_detail")
- @pytest.mark.parametrize("map_index", [None, -1])
def test_should_respond_200_with_existing_response(
self,
test_client: TestClient,
sample_ti_url_identifier: str,
- map_index: int | None,
sample_update_payload: dict[str, Any],
session: Session,
) -> None:
- query_param = "" if map_index is None else f"?map_index={map_index}"
response = test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json=sample_update_payload,
)
-
assert response.status_code == 200
assert response.json() == {
"params_input": {"input_1": 2},
@@ -325,23 +319,20 @@ class TestUpdateHITLDetailEndpoint:
}
audit_log = session.scalar(select(Log))
- _assert_sample_audit_log(audit_log, map_index=map_index)
+ _assert_sample_audit_log(audit_log)
@time_machine.travel(datetime(2025, 7, 3, 0, 0, 0), tick=False)
@pytest.mark.usefixtures("sample_hitl_detail_respondent")
- @pytest.mark.parametrize("map_index", [None, -1])
def test_should_respond_200_to_assigned_users(
self,
test_client: TestClient,
sample_ti_url_identifier: str,
- map_index: int | None,
sample_update_payload: dict[str, Any],
session: Session,
):
"""Test with an authorized user and the user is a respondent to the task."""
- query_param = "" if map_index is None else f"?map_index={map_index}"
response = test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json=sample_update_payload,
)
@@ -354,37 +345,32 @@ class TestUpdateHITLDetailEndpoint:
}
audit_log = session.scalar(select(Log))
- _assert_sample_audit_log(audit_log, map_index=map_index)
+ _assert_sample_audit_log(audit_log)
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
def test_should_respond_401(
self,
unauthenticated_test_client: TestClient,
sample_ti_url_identifier: str,
sample_update_payload: dict[str, Any],
- query_param: str,
) -> None:
response = unauthenticated_test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json=sample_update_payload,
)
assert response.status_code == 401
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
def test_should_respond_403(
self,
unauthorized_test_client: TestClient,
sample_ti_url_identifier: str,
sample_update_payload: dict[str, Any],
- query_param: str,
) -> None:
response = unauthorized_test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json=sample_update_payload,
)
assert response.status_code == 403
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
@time_machine.travel(datetime(2025, 7, 3, 0, 0, 0), tick=False)
@pytest.mark.usefixtures("sample_hitl_detail_non_respondent")
def test_should_respond_403_to_non_respondent_user(
@@ -392,58 +378,51 @@ class TestUpdateHITLDetailEndpoint:
test_client: TestClient,
sample_ti_url_identifier: str,
sample_update_payload: dict[str, Any],
- query_param: str,
):
"""Test with an authorized user but the user is not a respondent to the task."""
response = test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json=sample_update_payload,
)
assert response.status_code == 403
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
def test_should_respond_404_without_ti(
self,
test_client: TestClient,
sample_ti_url_identifier: str,
- query_param: str,
) -> None:
response = test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json={"chosen_options": ["Approve"], "params_input": {"input_1": 2}},
)
assert response.status_code == 404
assert response.json() == {"detail": expected_ti_not_found_error_msg}
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
def test_should_respond_404_without_hitl_detail(
self,
test_client: TestClient,
sample_ti_url_identifier: str,
sample_update_payload: dict[str, Any],
- query_param: str,
expected_hitl_detail_not_found_error_msg: str,
) -> None:
response = test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json=sample_update_payload,
)
assert response.status_code == 404
assert response.json() == {"detail": expected_hitl_detail_not_found_error_msg}
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
@time_machine.travel(datetime(2025, 7, 3, 0, 0, 0), tick=False)
@pytest.mark.usefixtures("sample_hitl_detail")
def test_should_respond_409(
self,
test_client: TestClient,
sample_ti_url_identifier: str,
- query_param: str,
sample_ti: TaskInstance,
) -> None:
response = test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json={"chosen_options": ["Approve"], "params_input": {"input_1": 2}},
)
@@ -457,7 +436,7 @@ class TestUpdateHITLDetailEndpoint:
assert response.json() == expected_response
response = test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json={"chosen_options": ["Approve"], "params_input": {"input_1": 3}},
)
assert response.status_code == 409
@@ -469,16 +448,14 @@ class TestUpdateHITLDetailEndpoint:
)
}
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
@pytest.mark.usefixtures("sample_hitl_detail")
def test_should_respond_422_with_empty_option(
self,
test_client: TestClient,
sample_ti_url_identifier: str,
- query_param: str,
) -> None:
response = test_client.patch(
- f"/hitlDetails/{sample_ti_url_identifier}{query_param}",
+ f"{sample_ti_url_identifier}/hitlDetails",
json={"chosen_options": [], "params_input": {"input_1": 2}},
)
@@ -486,59 +463,49 @@ class TestUpdateHITLDetailEndpoint:
class TestGetHITLDetailEndpoint:
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
@pytest.mark.usefixtures("sample_hitl_detail")
def test_should_respond_200_with_existing_response(
self,
test_client: TestClient,
sample_ti_url_identifier: str,
expected_sample_hitl_detail_dict: dict[str, Any],
- query_param: str,
) -> None:
- response = test_client.get(f"/hitlDetails/{sample_ti_url_identifier}{query_param}")
+ response = test_client.get(f"{sample_ti_url_identifier}/hitlDetails")
assert response.status_code == 200
assert response.json() == expected_sample_hitl_detail_dict
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
def test_should_respond_401(
self,
unauthenticated_test_client: TestClient,
sample_ti_url_identifier: str,
- query_param: str,
) -> None:
- response = unauthenticated_test_client.get(f"/hitlDetails/{sample_ti_url_identifier}{query_param}")
+ response = unauthenticated_test_client.get(f"{sample_ti_url_identifier}/hitlDetails")
assert response.status_code == 401
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
def test_should_respond_403(
self,
unauthorized_test_client: TestClient,
sample_ti_url_identifier: str,
- query_param: str,
) -> None:
- response = unauthorized_test_client.get(f"/hitlDetails/{sample_ti_url_identifier}{query_param}")
+ response = unauthorized_test_client.get(f"{sample_ti_url_identifier}/hitlDetails")
assert response.status_code == 403
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
def test_should_respond_404_without_ti(
self,
test_client: TestClient,
sample_ti_url_identifier: str,
- query_param: str,
) -> None:
- response = test_client.get(f"/hitlDetails/{sample_ti_url_identifier}{query_param}")
+ response = test_client.get(f"{sample_ti_url_identifier}/hitlDetails")
assert response.status_code == 404
assert response.json() == {"detail": expected_ti_not_found_error_msg}
- @pytest.mark.parametrize("query_param", ["", "?map_index=-1"])
def test_should_respond_404_without_hitl_detail(
self,
test_client: TestClient,
sample_ti_url_identifier: str,
expected_hitl_detail_not_found_error_msg: str,
- query_param: str,
) -> None:
- response = test_client.get(f"/hitlDetails/{sample_ti_url_identifier}{query_param}")
+ response = test_client.get(f"{sample_ti_url_identifier}/hitlDetails")
assert response.status_code == 404
assert response.json() == {"detail": expected_hitl_detail_not_found_error_msg}
@@ -550,7 +517,7 @@ class TestGetHITLDetailsEndpoint:
test_client: TestClient,
expected_sample_hitl_detail_dict: dict[str, Any],
) -> None:
- response = test_client.get("/hitlDetails/")
+ response = test_client.get("/dags/~/dagRuns/~/hitlDetails")
assert response.status_code == 200
assert response.json() == {
"hitl_details": [expected_sample_hitl_detail_dict],
@@ -564,8 +531,6 @@ class TestGetHITLDetailsEndpoint:
# ti related filter
({"dag_id_pattern": "hitl_dag"}, 5),
({"dag_id_pattern": "other_Dag_"}, 3),
- ({"dag_id": "hitl_dag_0"}, 1),
- ({"dag_run_id": "hitl_run_0"}, 1),
({"task_id": "hitl_task_0"}, 1),
({"task_id_pattern": "another_hitl"}, 3),
({"state": "running"}, 5),
@@ -581,8 +546,6 @@ class TestGetHITLDetailsEndpoint:
ids=[
"dag_id_pattern_hitl_dag",
"dag_id_pattern_other_dag",
- "dag_id",
- "dag_run_id",
"task_id_pattern",
"task_id",
"ti_state_running",
@@ -601,11 +564,39 @@ class TestGetHITLDetailsEndpoint:
params: dict[str, Any],
expected_ti_count: int,
) -> None:
- response = test_client.get("/hitlDetails/", params=params)
+ response = test_client.get("/dags/~/dagRuns/~/hitlDetails", params=params)
assert response.status_code == 200
assert response.json()["total_entries"] == expected_ti_count
assert len(response.json()["hitl_details"]) == expected_ti_count
+ @pytest.mark.usefixtures("sample_hitl_details")
+ def test_should_respond_200_with_existing_response_and_concrete_query(
+ self,
+ test_client: TestClient,
+ ) -> None:
+ response = test_client.get("/dags/hitl_dag_0/dagRuns/hitl_run_0/hitlDetails")
+ assert response.status_code == 200
+ assert response.json() == {
+ "hitl_details": [
+ {
+ "task_instance": mock.ANY,
+ "options": ["Approve", "Reject"],
+ "subject": "This is subject 0",
+ "body": "this is body 0",
+ "defaults": ["Approve"],
+ "multiple": False,
+ "params": {"input_1": 1},
+ "assigned_users": [],
+ "responded_by_user": None,
+ "responded_at": None,
+ "chosen_options": None,
+ "params_input": {},
+ "response_received": False,
+ }
+ ],
+ "total_entries": 1,
+ }
+
@pytest.mark.usefixtures("sample_hitl_details")
@pytest.mark.parametrize("asc_desc_mark", ["", "-"], ids=["asc", "desc"])
@pytest.mark.parametrize(
@@ -642,7 +633,9 @@ class TestGetHITLDetailsEndpoint:
) -> None:
reverse = asc_desc_mark == "-"
- response = test_client.get("/hitlDetails/", params={"order_by": f"{asc_desc_mark}{key}"})
+ response = test_client.get(
+ "/dags/~/dagRuns/~/hitlDetails", params={"order_by": f"{asc_desc_mark}{key}"}
+ )
data = response.json()
hitl_details = data["hitl_details"]
@@ -664,7 +657,7 @@ class TestGetHITLDetailsEndpoint:
assert hitl_details == sorted_hitl_details
def test_should_respond_200_without_response(self, test_client: TestClient) -> None:
- response = test_client.get("/hitlDetails/")
+ response = test_client.get("/dags/~/dagRuns/~/hitlDetails")
assert response.status_code == 200
assert response.json() == {
"hitl_details": [],
@@ -672,9 +665,9 @@ class TestGetHITLDetailsEndpoint:
}
def test_should_respond_401(self, unauthenticated_test_client: TestClient) -> None:
- response = unauthenticated_test_client.get("/hitlDetails/")
+ response = unauthenticated_test_client.get("/dags/~/dagRuns/~/hitlDetails")
assert response.status_code == 401
def test_should_respond_403(self, unauthorized_test_client: TestClient) -> None:
- response = unauthorized_test_client.get("/hitlDetails/")
+ response = unauthorized_test_client.get("/dags/~/dagRuns/~/hitlDetails")
assert response.status_code == 403
(airflow) 05/06: Front end for hitl endpoint update (#55674)
Posted by ka...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kaxilnaik pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit f6377f66954c50e926163f2b41651fb0ea2f45a9
Author: Pierre Jeambrun <pi...@gmail.com>
AuthorDate: Mon Sep 15 15:32:54 2025 -0600
Front end for hitl endpoint update (#55674)
Follow up of https://github.com/apache/airflow/pull/55603.
Only the last commit is relevant. Tested locally all seems good.
(cherry picked from commit c14c18e5ae9f1bdb065c90b585bc2f3c14460574)
---
.../src/airflow/ui/src/components/NeedsReviewButton.tsx | 8 ++++----
.../src/airflow/ui/src/hooks/useRequiredActionTabs.ts | 6 +++---
.../src/pages/HITLTaskInstances/HITLTaskInstances.tsx | 8 ++++----
.../airflow/ui/src/pages/TaskInstance/HITLResponse.tsx | 17 ++++++++++-------
.../src/airflow/ui/src/queries/useDeleteDagRun.ts | 4 ++--
.../src/airflow/ui/src/queries/useDeleteTaskInstance.ts | 4 ++--
.../src/airflow/ui/src/queries/useUpdateHITLDetail.ts | 14 +++++++-------
7 files changed, 32 insertions(+), 29 deletions(-)
diff --git a/airflow-core/src/airflow/ui/src/components/NeedsReviewButton.tsx b/airflow-core/src/airflow/ui/src/components/NeedsReviewButton.tsx
index fcec3a8fe1d..6ceb54a3d05 100644
--- a/airflow-core/src/airflow/ui/src/components/NeedsReviewButton.tsx
+++ b/airflow-core/src/airflow/ui/src/components/NeedsReviewButton.tsx
@@ -20,7 +20,7 @@ import { Box } from "@chakra-ui/react";
import { useTranslation } from "react-i18next";
import { LuUserRoundPen } from "react-icons/lu";
-import { useHumanInTheLoopServiceGetHitlDetails } from "openapi/queries";
+import { useTaskInstanceServiceGetHitlDetails } from "openapi/queries";
import { useAutoRefresh } from "src/utils/query";
import { StatsCard } from "./StatsCard";
@@ -37,10 +37,10 @@ export const NeedsReviewButton = ({
readonly taskId?: string;
}) => {
const hookAutoRefresh = useAutoRefresh({ dagId });
- const { data: hitlStatsData, isLoading } = useHumanInTheLoopServiceGetHitlDetails(
+ const { data: hitlStatsData, isLoading } = useTaskInstanceServiceGetHitlDetails(
{
- dagId,
- dagRunId: runId,
+ dagId: dagId ?? "~",
+ dagRunId: runId ?? "~",
responseReceived: false,
state: ["deferred"],
taskId,
diff --git a/airflow-core/src/airflow/ui/src/hooks/useRequiredActionTabs.ts b/airflow-core/src/airflow/ui/src/hooks/useRequiredActionTabs.ts
index ddef7c64b08..c187f7b2415 100644
--- a/airflow-core/src/airflow/ui/src/hooks/useRequiredActionTabs.ts
+++ b/airflow-core/src/airflow/ui/src/hooks/useRequiredActionTabs.ts
@@ -20,7 +20,7 @@ import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { useLocation, useNavigate } from "react-router-dom";
-import { useHumanInTheLoopServiceGetHitlDetails } from "openapi/queries";
+import { useTaskInstanceServiceGetHitlDetails } from "openapi/queries";
export type HITLQueryParams = {
dagId: string;
@@ -70,10 +70,10 @@ export const useRequiredActionTabs = (
return location.pathname.replace("/required_actions", "");
})();
- const { data: hitlData, isLoading: isLoadingHitl } = useHumanInTheLoopServiceGetHitlDetails(
+ const { data: hitlData, isLoading: isLoadingHitl } = useTaskInstanceServiceGetHitlDetails(
{
dagId: hitlParams.dagId,
- dagRunId: hitlParams.dagRunId,
+ dagRunId: hitlParams.dagRunId ?? "~",
taskId: hitlParams.taskId,
taskIdPattern: hitlParams.taskIdPattern,
},
diff --git a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
index 29e762ee636..65fb4a33db9 100644
--- a/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLTaskInstances.tsx
@@ -23,7 +23,7 @@ import { useCallback } from "react";
import { useTranslation } from "react-i18next";
import { Link as RouterLink, useParams, useSearchParams } from "react-router-dom";
-import { useHumanInTheLoopServiceGetHitlDetails } from "openapi/queries";
+import { useTaskInstanceServiceGetHitlDetails } from "openapi/queries";
import type { HITLDetail } from "openapi/requests/types.gen";
import { DataTable } from "src/components/DataTable";
import { useTableURLState } from "src/components/DataTable/useTableUrlState";
@@ -122,9 +122,9 @@ export const HITLTaskInstances = () => {
const [sort] = sorting;
const responseReceived = searchParams.get(RESPONSE_RECEIVED_PARAM);
- const { data, error, isLoading } = useHumanInTheLoopServiceGetHitlDetails({
- dagId,
- dagRunId: runId,
+ const { data, error, isLoading } = useTaskInstanceServiceGetHitlDetails({
+ dagId: dagId ?? "~",
+ dagRunId: runId ?? "~",
limit: pagination.pageSize,
offset: pagination.pageIndex * pagination.pageSize,
orderBy: sort ? [`${sort.desc ? "-" : ""}${sort.id}`] : [],
diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstance/HITLResponse.tsx b/airflow-core/src/airflow/ui/src/pages/TaskInstance/HITLResponse.tsx
index 95e52b145a2..11072fe862e 100644
--- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/HITLResponse.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/HITLResponse.tsx
@@ -19,7 +19,7 @@
import { Box } from "@chakra-ui/react";
import { useParams } from "react-router-dom";
-import { useHumanInTheLoopServiceGetHitlDetail } from "openapi/queries";
+import { useTaskInstanceServiceGetHitlDetail } from "openapi/queries";
import { ProgressBar } from "src/components/ui";
import { HITLResponseForm } from "../HITLTaskInstances/HITLResponseForm";
@@ -27,12 +27,15 @@ import { HITLResponseForm } from "../HITLTaskInstances/HITLResponseForm";
export const HITLResponse = () => {
const { dagId, mapIndex, runId, taskId } = useParams();
- const { data: hitlDetail } = useHumanInTheLoopServiceGetHitlDetail({
- dagId: dagId ?? "~",
- dagRunId: runId ?? "~",
- mapIndex: Number(mapIndex ?? -1),
- taskId: taskId ?? "~",
- });
+ const { data: hitlDetail } = useTaskInstanceServiceGetHitlDetail(
+ {
+ dagId: dagId ?? "",
+ dagRunId: runId ?? "",
+ mapIndex: Number(mapIndex ?? -1),
+ taskId: taskId ?? "",
+ },
+ undefined,
+ );
if (!hitlDetail?.task_instance) {
return (
diff --git a/airflow-core/src/airflow/ui/src/queries/useDeleteDagRun.ts b/airflow-core/src/airflow/ui/src/queries/useDeleteDagRun.ts
index 9535d31ae48..c5c75320551 100644
--- a/airflow-core/src/airflow/ui/src/queries/useDeleteDagRun.ts
+++ b/airflow-core/src/airflow/ui/src/queries/useDeleteDagRun.ts
@@ -24,7 +24,7 @@ import {
useDagRunServiceGetDagRunsKey,
UseDagRunServiceGetDagRunKeyFn,
useTaskInstanceServiceGetTaskInstancesKey,
- useHumanInTheLoopServiceGetHitlDetailsKey,
+ useTaskInstanceServiceGetHitlDetailsKey,
} from "openapi/queries";
import { toaster } from "src/components/ui";
@@ -51,7 +51,7 @@ export const useDeleteDagRun = ({ dagId, dagRunId, onSuccessConfirm }: DeleteDag
UseDagRunServiceGetDagRunKeyFn({ dagId, dagRunId }),
[useDagRunServiceGetDagRunsKey],
[useTaskInstanceServiceGetTaskInstancesKey],
- [useHumanInTheLoopServiceGetHitlDetailsKey],
+ [useTaskInstanceServiceGetHitlDetailsKey],
];
await Promise.all(queryKeys.map((key) => queryClient.invalidateQueries({ queryKey: key })));
diff --git a/airflow-core/src/airflow/ui/src/queries/useDeleteTaskInstance.ts b/airflow-core/src/airflow/ui/src/queries/useDeleteTaskInstance.ts
index 1ea27d22186..545168280e1 100644
--- a/airflow-core/src/airflow/ui/src/queries/useDeleteTaskInstance.ts
+++ b/airflow-core/src/airflow/ui/src/queries/useDeleteTaskInstance.ts
@@ -26,7 +26,7 @@ import {
useDagRunServiceGetDagRunsKey,
UseDagRunServiceGetDagRunKeyFn,
UseGridServiceGetGridTiSummariesKeyFn,
- useHumanInTheLoopServiceGetHitlDetailsKey,
+ useTaskInstanceServiceGetHitlDetailsKey,
} from "openapi/queries";
import { toaster } from "src/components/ui";
@@ -63,7 +63,7 @@ export const useDeleteTaskInstance = ({
[useDagRunServiceGetDagRunsKey],
[useTaskInstanceServiceGetTaskInstancesKey],
[useTaskInstanceServiceGetTaskInstanceKey, { dagId, dagRunId, mapIndex, taskId }],
- [useHumanInTheLoopServiceGetHitlDetailsKey],
+ [useTaskInstanceServiceGetHitlDetailsKey],
];
await Promise.all(queryKeys.map((key) => queryClient.invalidateQueries({ queryKey: key })));
diff --git a/airflow-core/src/airflow/ui/src/queries/useUpdateHITLDetail.ts b/airflow-core/src/airflow/ui/src/queries/useUpdateHITLDetail.ts
index 03d3246cc6b..f9dca74b281 100644
--- a/airflow-core/src/airflow/ui/src/queries/useUpdateHITLDetail.ts
+++ b/airflow-core/src/airflow/ui/src/queries/useUpdateHITLDetail.ts
@@ -23,9 +23,9 @@ import { useTranslation } from "react-i18next";
import {
UseDagRunServiceGetDagRunKeyFn,
useDagRunServiceGetDagRunsKey,
- useHumanInTheLoopServiceGetHitlDetailsKey,
- useHumanInTheLoopServiceGetHitlDetailKey,
- useHumanInTheLoopServiceUpdateHitlDetail,
+ useTaskInstanceServiceGetHitlDetailsKey,
+ useTaskInstanceServiceGetHitlDetailKey,
+ useTaskInstanceServiceUpdateHitlDetail,
useTaskInstanceServiceGetTaskInstanceKey,
useTaskInstanceServiceGetTaskInstancesKey,
} from "openapi/queries";
@@ -52,8 +52,8 @@ export const useUpdateHITLDetail = ({
[useDagRunServiceGetDagRunsKey],
[useTaskInstanceServiceGetTaskInstancesKey, { dagId, dagRunId }],
[useTaskInstanceServiceGetTaskInstanceKey, { dagId, dagRunId, mapIndex, taskId }],
- [useHumanInTheLoopServiceGetHitlDetailsKey, { dagIdPattern: dagId, dagRunId }],
- [useHumanInTheLoopServiceGetHitlDetailKey, { dagId, dagRunId }],
+ [useTaskInstanceServiceGetHitlDetailsKey, { dagIdPattern: dagId, dagRunId }],
+ [useTaskInstanceServiceGetHitlDetailKey, { dagId, dagRunId }],
];
await Promise.all(queryKeys.map((key) => queryClient.invalidateQueries({ queryKey: key })));
@@ -72,7 +72,7 @@ export const useUpdateHITLDetail = ({
});
};
- const { isPending, mutate } = useHumanInTheLoopServiceUpdateHitlDetail({
+ const { isPending, mutate } = useTaskInstanceServiceUpdateHitlDetail({
onError,
onSuccess,
});
@@ -82,7 +82,7 @@ export const useUpdateHITLDetail = ({
mutate({
dagId,
dagRunId,
- mapIndex,
+ mapIndex: mapIndex ?? -1,
requestBody: {
chosen_options: updateHITLResponseRequestBody.chosen_options ?? [],
params_input: updateHITLResponseRequestBody.params_input ?? {},
(airflow) 06/06: Update 3.1.0 release notes based on latest cherry-picks
Posted by ka...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kaxilnaik pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 50088d4d54a1a647e50e4f6e71d97c6d780dc311
Author: Kaxil Naik <ka...@apache.org>
AuthorDate: Mon Sep 15 20:15:17 2025 +0100
Update 3.1.0 release notes based on latest cherry-picks
---
RELEASE_NOTES.rst | 8 +++++++-
reproducible_build.yaml | 4 ++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst
index c5ec4258277..d7b93fd1bf6 100644
--- a/RELEASE_NOTES.rst
+++ b/RELEASE_NOTES.rst
@@ -339,6 +339,10 @@ Bug Fixes
- Fix ``XCom`` access in DAG processor callbacks for notifiers (#55542)
- Fix alignment of arrows in RTL mode for right-to-left languages (#55619)
- Fix connection form extras not inferring correct type in UI (#55492)
+- Fix incorrect log timestamps in UI when ``default_timezone`` is not UTC (#54431)
+- Fix handling of priority_weight for DAG processor callbacks (#55436)
+- Fix pointless requests from Gantt view when there is no Run ID (#55668)
+- Ensure filename and lineno of logger calls are present in Task Logs (#55581)
Miscellaneous
^^^^^^^^^^^^^
@@ -363,11 +367,12 @@ Miscellaneous
- Optimize Gantt group expansion with de-bouncing and deferred rendering (#55334)
- Differentiate between triggers and watchers currently running for better visibility (#55376)
- Update color palette and leverage Chakra semantic tokens (#53981)
-- Removed unused config: ``dag_stale_not_seen_duration`` (#55601)
+- Removed unused config: ``dag_stale_not_seen_duration`` (#55601, #55684)
- Update UI's query client strategy for improved performance (#55528)
- Unify datetime format across the UI for consistency (#55572)
- Mark React Apps as Experimental for Airflow 3.1 release (#55478)
- Improve OOM error messaging for clearer task failure diagnosis (#55602)
+- Display responder username for better audit trail in HITL workflows (#55509)
Doc Only Changes
^^^^^^^^^^^^^^^^
@@ -688,6 +693,7 @@ Bug Fixes
- Fix OpenAPI schema for ``get_log`` API (#50547)
- Remove ``logical_date`` check when validating inlets and outlets (#51464)
- Guard ``ti`` update state and set task to fail if exception encountered (#51295)
+- Fix task log URL generation with various ``base_url`` formats (#55699)
Miscellaneous
"""""""""""""
diff --git a/reproducible_build.yaml b/reproducible_build.yaml
index 79e6df603cc..ea5bbe829af 100644
--- a/reproducible_build.yaml
+++ b/reproducible_build.yaml
@@ -1,2 +1,2 @@
-release-notes-hash: 0638f4d3625aa66fe5660ac969f71c72
-source-date-epoch: 1757895053
+release-notes-hash: 733a4ea2f18039832fd3edbcf4102769
+source-date-epoch: 1757972272
(airflow) 02/06: #55020 gantt view is not getting updatedin realtime (#55130)
Posted by ka...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kaxilnaik pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 868748d2fdea3ccea2f9b366d3d71cdc987cfe7d
Author: Yiming Peng <yi...@gmail.com>
AuthorDate: Tue Sep 16 08:52:55 2025 +1200
#55020 gantt view is not getting updatedin realtime (#55130)
* Fix real-time updates for running tasks in Gantt chart view
* Fix linting
* Use DEFAULT_DATETIME_FORMAT_WITH_TZ as recommended
* Fix linting issue
(cherry picked from commit 67b0c79ef704ce412cf9b4055a66de0eacbf251f)
---
.../airflow/ui/src/layouts/Details/Gantt/Gantt.tsx | 18 +-
.../airflow/ui/src/layouts/Details/Gantt/utils.ts | 194 +++++++++++----------
2 files changed, 113 insertions(+), 99 deletions(-)
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
index 4e11f390224..444cd6c9ce8 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/Gantt.tsx
@@ -33,6 +33,7 @@ import {
import "chart.js/auto";
import "chartjs-adapter-dayjs-4/dist/chartjs-adapter-dayjs-4.esm";
import annotationPlugin from "chartjs-plugin-annotation";
+import dayjs from "dayjs";
import { useMemo, useRef, useDeferredValue } from "react";
import { Bar } from "react-chartjs-2";
import { useTranslation } from "react-i18next";
@@ -48,7 +49,7 @@ import { useGridStructure } from "src/queries/useGridStructure";
import { useGridTiSummaries } from "src/queries/useGridTISummaries";
import { getComputedCSSVariableValue } from "src/theme";
import { isStatePending, useAutoRefresh } from "src/utils";
-import { DEFAULT_DATETIME_FORMAT, formatDate } from "src/utils/datetimeUtils";
+import { DEFAULT_DATETIME_FORMAT_WITH_TZ, formatDate } from "src/utils/datetimeUtils";
import { createHandleBarClick, createChartOptions } from "./utils";
@@ -127,6 +128,8 @@ export const Gantt = ({ limit }: Props) => {
const isLoading = runsLoading || structureLoading || summariesLoading || tiLoading;
+ const currentTime = dayjs().tz(selectedTimezone).format(DEFAULT_DATETIME_FORMAT_WITH_TZ);
+
const data = useMemo(() => {
if (isLoading || runId === "") {
return [];
@@ -147,8 +150,8 @@ export const Gantt = ({ limit }: Props) => {
state: gridSummary.state,
taskId: gridSummary.task_id,
x: [
- formatDate(gridSummary.min_start_date, selectedTimezone, DEFAULT_DATETIME_FORMAT),
- formatDate(gridSummary.max_end_date, selectedTimezone, DEFAULT_DATETIME_FORMAT),
+ formatDate(gridSummary.min_start_date, selectedTimezone, DEFAULT_DATETIME_FORMAT_WITH_TZ),
+ formatDate(gridSummary.max_end_date, selectedTimezone, DEFAULT_DATETIME_FORMAT_WITH_TZ),
],
y: gridSummary.task_id,
};
@@ -157,14 +160,17 @@ export const Gantt = ({ limit }: Props) => {
const taskInstance = taskInstances.find((ti) => ti.task_id === node.id);
if (taskInstance) {
+ const hasTaskRunning = isStatePending(taskInstance.state);
+ const endTime = hasTaskRunning ? currentTime : taskInstance.end_date;
+
return {
isGroup: node.isGroup,
isMapped: node.is_mapped,
state: taskInstance.state,
taskId: taskInstance.task_id,
x: [
- formatDate(taskInstance.start_date, selectedTimezone, DEFAULT_DATETIME_FORMAT),
- formatDate(taskInstance.end_date, selectedTimezone, DEFAULT_DATETIME_FORMAT),
+ formatDate(taskInstance.start_date, selectedTimezone, DEFAULT_DATETIME_FORMAT_WITH_TZ),
+ formatDate(endTime, selectedTimezone, DEFAULT_DATETIME_FORMAT_WITH_TZ),
],
y: taskInstance.task_id,
};
@@ -174,7 +180,7 @@ export const Gantt = ({ limit }: Props) => {
return undefined;
})
.filter((item) => item !== undefined);
- }, [flatNodes, gridTiSummaries, taskInstancesData, selectedTimezone, isLoading, runId]);
+ }, [flatNodes, gridTiSummaries, taskInstancesData, selectedTimezone, isLoading, runId, currentTime]);
// Get all unique states and their colors
const states = [...new Set(data.map((item) => item.state ?? "none"))];
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.ts b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.ts
index d5f937ab42e..df93b963910 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.ts
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Gantt/utils.ts
@@ -17,11 +17,12 @@
* under the License.
*/
import type { ChartEvent, ActiveElement, TooltipItem } from "chart.js";
+import dayjs from "dayjs";
import type { TFunction } from "i18next";
import type { NavigateFunction, Location } from "react-router-dom";
import type { GridRunsResponse, TaskInstanceState } from "openapi/requests";
-import { getDuration } from "src/utils";
+import { getDuration, isStatePending } from "src/utils";
import { formatDate } from "src/utils/datetimeUtils";
import { buildTaskInstanceUrl } from "src/utils/links";
@@ -91,107 +92,114 @@ export const createChartOptions = ({
selectedRun,
selectedTimezone,
translate,
-}: ChartOptionsParams) => ({
- animation: {
- duration: 150,
- easing: "linear" as const,
- },
- indexAxis: "y" as const,
- maintainAspectRatio: false,
- onClick: handleBarClick,
- onHover: (event: ChartEvent, elements: Array<ActiveElement>) => {
- const target = event.native?.target as HTMLElement | undefined;
+}: ChartOptionsParams) => {
+ const isActivePending = isStatePending(selectedRun?.state);
+ const effectiveEndDate = isActivePending
+ ? dayjs().tz(selectedTimezone).format("YYYY-MM-DD HH:mm:ss")
+ : selectedRun?.end_date;
- if (target) {
- target.style.cursor = elements.length > 0 ? "pointer" : "default";
- }
- },
- plugins: {
- annotation: {
- annotations:
- selectedId === undefined || selectedId === ""
- ? []
- : [
- {
- backgroundColor: selectedItemColor,
- borderWidth: 0,
- drawTime: "beforeDatasetsDraw" as const,
- type: "box" as const,
- xMax: "max" as const,
- xMin: "min" as const,
- yMax: data.findIndex((dataItem) => dataItem.y === selectedId) + 0.5,
- yMin: data.findIndex((dataItem) => dataItem.y === selectedId) - 0.5,
- },
- ],
+ return {
+ animation: {
+ duration: 150,
+ easing: "linear" as const,
},
- legend: {
- display: false,
+ indexAxis: "y" as const,
+ maintainAspectRatio: false,
+ onClick: handleBarClick,
+ onHover: (event: ChartEvent, elements: Array<ActiveElement>) => {
+ const target = event.native?.target as HTMLElement | undefined;
+
+ if (target) {
+ target.style.cursor = elements.length > 0 ? "pointer" : "default";
+ }
},
- tooltip: {
- callbacks: {
- afterBody(tooltipItems: Array<TooltipItem<"bar">>) {
- const taskInstance = data.find((dataItem) => dataItem.y === tooltipItems[0]?.label);
- const startDate = formatDate(taskInstance?.x[0], selectedTimezone);
- const endDate = formatDate(taskInstance?.x[1], selectedTimezone);
+ plugins: {
+ annotation: {
+ annotations:
+ selectedId === undefined || selectedId === ""
+ ? []
+ : [
+ {
+ backgroundColor: selectedItemColor,
+ borderWidth: 0,
+ drawTime: "beforeDatasetsDraw" as const,
+ type: "box" as const,
+ xMax: "max" as const,
+ xMin: "min" as const,
+ yMax: data.findIndex((dataItem) => dataItem.y === selectedId) + 0.5,
+ yMin: data.findIndex((dataItem) => dataItem.y === selectedId) - 0.5,
+ },
+ ],
+ },
+ legend: {
+ display: false,
+ },
+ tooltip: {
+ callbacks: {
+ afterBody(tooltipItems: Array<TooltipItem<"bar">>) {
+ const taskInstance = data.find((dataItem) => dataItem.y === tooltipItems[0]?.label);
+ const startDate = formatDate(taskInstance?.x[0], selectedTimezone);
+ const endDate = formatDate(taskInstance?.x[1], selectedTimezone);
- return [
- `${translate("startDate")}: ${startDate}`,
- `${translate("endDate")}: ${endDate}`,
- `${translate("duration")}: ${getDuration(taskInstance?.x[0], taskInstance?.x[1])}`,
- ];
- },
- label(tooltipItem: TooltipItem<"bar">) {
- const { label } = tooltipItem;
- const taskInstance = data.find((dataItem) => dataItem.y === label);
+ return [
+ `${translate("startDate")}: ${startDate}`,
+ `${translate("endDate")}: ${endDate}`,
+ `${translate("duration")}: ${getDuration(taskInstance?.x[0], taskInstance?.x[1])}`,
+ ];
+ },
+ label(tooltipItem: TooltipItem<"bar">) {
+ const { label } = tooltipItem;
+ const taskInstance = data.find((dataItem) => dataItem.y === label);
- return `${translate("state")}: ${translate(`states.${taskInstance?.state}`)}`;
+ return `${translate("state")}: ${translate(`states.${taskInstance?.state}`)}`;
+ },
},
},
},
- },
- resizeDelay: 100,
- responsive: true,
- scales: {
- x: {
- grid: {
- color: gridColor,
- display: true,
- },
- max:
- data.length > 0
- ? (() => {
- const maxTime = Math.max(...data.map((item) => new Date(item.x[1] ?? "").getTime()));
- const minTime = Math.min(...data.map((item) => new Date(item.x[0] ?? "").getTime()));
- const totalDuration = maxTime - minTime;
+ resizeDelay: 100,
+ responsive: true,
+ scales: {
+ x: {
+ grid: {
+ color: gridColor,
+ display: true,
+ },
+ max:
+ data.length > 0
+ ? (() => {
+ const maxTime = Math.max(...data.map((item) => new Date(item.x[1] ?? "").getTime()));
+ const minTime = Math.min(...data.map((item) => new Date(item.x[0] ?? "").getTime()));
+ const totalDuration = maxTime - minTime;
- // add 5% to the max time to avoid the last tick being cut off
- return maxTime + totalDuration * 0.05;
- })()
- : formatDate(selectedRun?.end_date, selectedTimezone),
- min:
- data.length > 0
- ? Math.min(...data.map((item) => new Date(item.x[0] ?? "").getTime()))
- : formatDate(selectedRun?.start_date, selectedTimezone),
- position: "top" as const,
- stacked: true,
- ticks: {
- align: "start" as const,
- callback: (value: number | string) => formatDate(value, selectedTimezone, "HH:mm:ss"),
- maxRotation: 8,
- maxTicksLimit: 8,
- minRotation: 8,
- },
- type: "time" as const,
- },
- y: {
- grid: {
- color: gridColor,
- display: true,
+ // add 5% to the max time to avoid the last tick being cut off
+ return maxTime + totalDuration * 0.05;
+ })()
+ : formatDate(effectiveEndDate, selectedTimezone),
+ min:
+ data.length > 0
+ ? Math.min(...data.map((item) => new Date(item.x[0] ?? "").getTime()))
+ : formatDate(selectedRun?.start_date, selectedTimezone),
+ position: "top" as const,
+ stacked: true,
+ ticks: {
+ align: "start" as const,
+ callback: (value: number | string) => formatDate(value, selectedTimezone, "HH:mm:ss"),
+ maxRotation: 8,
+ maxTicksLimit: 8,
+ minRotation: 8,
+ },
+ type: "time" as const,
},
- stacked: true,
- ticks: {
- display: false,
+ y: {
+ grid: {
+ color: gridColor,
+ display: true,
+ },
+ stacked: true,
+ ticks: {
+ display: false,
+ },
},
},
- },
-});
+ };
+};
(airflow) 03/06: Fix task log URL generation with various `base_url` formats (#55699)
Posted by ka...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kaxilnaik pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 09560358e062f238e89018dc45dba44fb382b747
Author: Kaxil Naik <ka...@apache.org>
AuthorDate: Mon Sep 15 22:27:33 2025 +0100
Fix task log URL generation with various `base_url` formats (#55699)
The `RuntimeTaskInstance.log_url` property
incorrectly concatenated base_url with the path, causing malformed URLs
when base_url didn't end with a slash.
Fixes #54247
Closes https://github.com/apache/airflow/pull/54248
Closes https://github.com/apache/airflow/pull/53884
(cherry picked from commit 3e1638250fb8f58a399ad8c5946dbb77a079f63d)
---
airflow-core/src/airflow/models/taskinstance.py | 2 +-
.../src/airflow/sdk/execution_time/task_runner.py | 19 +---------------
.../task_sdk/execution_time/test_task_runner.py | 25 ++++++++++++++++++++++
3 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/airflow-core/src/airflow/models/taskinstance.py b/airflow-core/src/airflow/models/taskinstance.py
index 36193d077f3..72a5ab0b24b 100644
--- a/airflow-core/src/airflow/models/taskinstance.py
+++ b/airflow-core/src/airflow/models/taskinstance.py
@@ -622,7 +622,7 @@ class TaskInstance(Base, LoggingMixin):
base_url = conf.get("api", "base_url", fallback="http://localhost:8080/")
map_index = f"/mapped/{self.map_index}" if self.map_index >= 0 else ""
try_number = f"?try_number={self.try_number}" if self.try_number > 0 else ""
- _log_uri = f"{base_url}dags/{self.dag_id}/runs/{run_id}/tasks/{self.task_id}{map_index}{try_number}"
+ _log_uri = f"{base_url.rstrip('/')}/dags/{self.dag_id}/runs/{run_id}/tasks/{self.task_id}{map_index}{try_number}"
return _log_uri
diff --git a/task-sdk/src/airflow/sdk/execution_time/task_runner.py b/task-sdk/src/airflow/sdk/execution_time/task_runner.py
index 02d5eb23996..bb92ff00154 100644
--- a/task-sdk/src/airflow/sdk/execution_time/task_runner.py
+++ b/task-sdk/src/airflow/sdk/execution_time/task_runner.py
@@ -562,7 +562,7 @@ class RuntimeTaskInstance(TaskInstance):
try_number = (
f"?try_number={try_number_value}" if try_number_value is not None and try_number_value > 0 else ""
)
- _log_uri = f"{base_url}dags/{self.dag_id}/runs/{run_id}/tasks/{self.task_id}{map_index}{try_number}"
+ _log_uri = f"{base_url.rstrip('/')}/dags/{self.dag_id}/runs/{run_id}/tasks/{self.task_id}{map_index}{try_number}"
return _log_uri
@property
@@ -599,23 +599,6 @@ def _xcom_push_to_db(ti: RuntimeTaskInstance, key: str, value: Any) -> None:
)
-def get_log_url_from_ti(ti: RuntimeTaskInstance) -> str:
- from urllib.parse import quote
-
- from airflow.configuration import conf
-
- run_id = quote(ti.run_id)
- base_url = conf.get("api", "base_url", fallback="http://localhost:8080/")
- map_index_value = getattr(ti, "map_index", -1)
- map_index = f"/mapped/{map_index_value}" if map_index_value is not None and map_index_value >= 0 else ""
- try_number_value = getattr(ti, "try_number", 0)
- try_number = (
- f"?try_number={try_number_value}" if try_number_value is not None and try_number_value > 0 else ""
- )
- _log_uri = f"{base_url}dags/{ti.dag_id}/runs/{run_id}/tasks/{ti.task_id}{map_index}{try_number}"
- return _log_uri
-
-
def parse(what: StartupDetails, log: Logger) -> RuntimeTaskInstance:
# TODO: Task-SDK:
# Using DagBag here is about 98% wrong, but it'll do for now
diff --git a/task-sdk/tests/task_sdk/execution_time/test_task_runner.py b/task-sdk/tests/task_sdk/execution_time/test_task_runner.py
index 65c236a051a..525d137a481 100644
--- a/task-sdk/tests/task_sdk/execution_time/test_task_runner.py
+++ b/task-sdk/tests/task_sdk/execution_time/test_task_runner.py
@@ -2691,6 +2691,31 @@ class TestTaskRunnerCallsCallbacks:
assert state == expected_state
assert collected_results == expected_results
+ @pytest.mark.parametrize(
+ ["base_url", "expected_url"],
+ [
+ ("http://localhost:8080/", "http://localhost:8080/dags/test_dag/runs/test_run/tasks/test_task"),
+ ("http://localhost:8080", "http://localhost:8080/dags/test_dag/runs/test_run/tasks/test_task"),
+ (
+ "https://airflow.example.com/",
+ "https://airflow.example.com/dags/test_dag/runs/test_run/tasks/test_task",
+ ),
+ (
+ "https://airflow.example.com",
+ "https://airflow.example.com/dags/test_dag/runs/test_run/tasks/test_task",
+ ),
+ ],
+ ids=["localhost_with_slash", "localhost_no_slash", "domain_with_slash", "domain_no_slash"],
+ )
+ def test_runtime_task_instance_log_url_property(self, create_runtime_ti, base_url, expected_url):
+ """Test that RuntimeTaskInstance.log_url property correctly handles various base_url formats."""
+ task = BaseOperator(task_id="test_task")
+ runtime_ti = create_runtime_ti(task=task, dag_id="test_dag", run_id="test_run", try_number=0)
+
+ with patch("airflow.configuration.conf.get", return_value=base_url):
+ log_url = runtime_ti.log_url
+ assert log_url == expected_url
+
def test_task_runner_on_failure_callback_context(self, create_runtime_ti):
"""Test that on_failure_callback context has end_date and duration."""
from airflow.exceptions import AirflowException
(airflow) 01/06: fix(docker/entrypoint_prod.sh): prevent the script from code 2 after db migrate success (#52928)
Posted by ka...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
kaxilnaik pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit f021bba05b5e108db63e53c7675e01b237d5adb9
Author: Creative Ataraxia <10...@users.noreply.github.com>
AuthorDate: Tue Sep 16 03:20:11 2025 +0800
fix(docker/entrypoint_prod.sh): prevent the script from code 2 after db migrate success (#52928)
* fix(docker): prevent airflow-init from failing after db migrate where no command is passed-in
* docs(docker-stack-docs/entrypoint.rst): container clean exit behavior with _AIRFLOW_DB_MIGRATE and no command
* chore: update inlined Dockerfile after entrypoint.sh script change
---------
Co-authored-by: Roy M. <ro...@gmail.com>
(cherry picked from commit 90f9c7026a8ca41a238125fdc7adaa1e49d189de)
---
Dockerfile | 5 +++++
docker-stack-docs/entrypoint.rst | 9 ++++++---
scripts/docker/entrypoint_prod.sh | 6 ++++++
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 1b6d02a68e8..113bed816e7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1619,6 +1619,11 @@ if [[ ${AIRFLOW_COMMAND} =~ ^(scheduler|celery)$ ]] \
wait_for_celery_broker
fi
+if [[ "$#" -eq 0 && "${_AIRFLOW_DB_MIGRATE}" == "true" ]]; then
+ echo "[INFO] No commands passed and _AIRFLOW_DB_MIGRATE=true. Exiting script with code 0."
+ exit 0
+fi
+
exec "airflow" "${@}"
EOF
diff --git a/docker-stack-docs/entrypoint.rst b/docker-stack-docs/entrypoint.rst
index bcfde3e7053..a1d6e894cde 100644
--- a/docker-stack-docs/entrypoint.rst
+++ b/docker-stack-docs/entrypoint.rst
@@ -318,9 +318,12 @@ Upgrading Airflow DB
If you set :envvar:`_AIRFLOW_DB_MIGRATE` variable to a non-empty value, the entrypoint will run
the ``airflow db migrate`` command right after verifying the connection. You can also use this
when you are running Airflow with internal SQLite database (default) to upgrade the db and create
-admin users at entrypoint, so that you can start the webserver immediately. Note - using SQLite is
-intended only for testing purpose, never use SQLite in production as it has severe limitations when it
-comes to concurrency.
+admin users at entrypoint, so that you can start the webserver immediately. If no command is
+provided to the container and :envvar:`_AIRFLOW_DB_MIGRATE` is set, the container will exit
+cleanly after completing the database migration. This allows one-off init containers
+(such as ``airflow-init``) to perform setup without requiring a placeholder command to suppress
+CLI errors. Note - using SQLite is intended only for testing purpose, never use SQLite in
+production as it has severe limitations when it comes to concurrency.
Creating admin user
...................
diff --git a/scripts/docker/entrypoint_prod.sh b/scripts/docker/entrypoint_prod.sh
index cd7a600641f..88135c145c1 100755
--- a/scripts/docker/entrypoint_prod.sh
+++ b/scripts/docker/entrypoint_prod.sh
@@ -337,4 +337,10 @@ if [[ ${AIRFLOW_COMMAND} =~ ^(scheduler|celery)$ ]] \
wait_for_celery_broker
fi
+# Exit cleanly if the init was only intended to migrate DB
+if [[ "$#" -eq 0 && "${_AIRFLOW_DB_MIGRATE}" == "true" ]]; then
+ echo "[INFO] No commands passed and _AIRFLOW_DB_MIGRATE=true. Exiting script with code 0."
+ exit 0
+fi
+
exec "airflow" "${@}"