Skip to content

fix(local): resolve PIPELINE_JOB_RESOURCE_NAME, CREATE_TIME, and SCHEDULE_TIME placeholders#13426

Open
shreeharshshinde wants to merge 2 commits into
kubeflow:masterfrom
shreeharshshinde:fix/placeholder-replacement-13424
Open

fix(local): resolve PIPELINE_JOB_RESOURCE_NAME, CREATE_TIME, and SCHEDULE_TIME placeholders#13426
shreeharshshinde wants to merge 2 commits into
kubeflow:masterfrom
shreeharshshinde:fix/placeholder-replacement-13424

Conversation

@shreeharshshinde
Copy link
Copy Markdown

Problem

Fixes #13424.

Three dsl placeholders were silently left unresolved when running pipelines locally via kfp.local. Components using these placeholders received the raw placeholder string instead of the actual runtime value.

Affected placeholders

Placeholder Expected Runtime Value
dsl.PIPELINE_JOB_RESOURCE_NAME_PLACEHOLDER Argo Workflow object name (pipeline run resource name)
dsl.PIPELINE_JOB_CREATE_TIME_UTC_PLACEHOLDER UTC timestamp when the pipeline job was created
dsl.PIPELINE_JOB_SCHEDULE_TIME_UTC_PLACEHOLDER UTC timestamp for which the pipeline job was scheduled

All other job/task placeholders were already resolved correctly:

  • PIPELINE_JOB_NAME
  • PIPELINE_JOB_ID
  • PIPELINE_TASK_NAME
  • PIPELINE_TASK_ID
  • PIPELINE_ROOT

These three placeholders were simply missing from the local placeholder resolution map.


Root Cause

resolve_individual_placeholder() in:

sdk/python/kfp/local/placeholder_utils.py

maintains a PLACEHOLDERS mapping that resolves placeholder strings to runtime values.

Although the following placeholders were defined in kfp.dsl, they were never added to this mapping:

  • PIPELINE_JOB_RESOURCE_NAME_PLACEHOLDER
  • PIPELINE_JOB_CREATE_TIME_UTC_PLACEHOLDER
  • PIPELINE_JOB_SCHEDULE_TIME_UTC_PLACEHOLDER

As a result, local execution returned unresolved raw placeholder strings.


Changes

sdk/python/kfp/local/placeholder_utils.py

Added support for the following placeholders:

Placeholder Resolved Value
PIPELINE_JOB_RESOURCE_NAME_PLACEHOLDER pipeline_resource_name
PIPELINE_JOB_CREATE_TIME_UTC_PLACEHOLDER Current UTC timestamp in ISO 8601 format
PIPELINE_JOB_SCHEDULE_TIME_UTC_PLACEHOLDER Current UTC timestamp in ISO 8601 format

Tests

sdk/python/kfp/local/placeholder_utils_test.py

Added coverage for the newly supported placeholders:

  • Added {{$.pipeline_job_resource_name}} to test_constant_placeholders
  • Added test_pipeline_job_create_time_utc_placeholder
  • Added test_pipeline_job_schedule_time_utc_placeholder

The timestamp tests validate that resolved values match the expected ISO 8601 UTC format.


  Add PIPELINE_JOB_RESOURCE_NAME_PLACEHOLDER,
  PIPELINE_JOB_CREATE_TIME_UTC_PLACEHOLDER, and
  PIPELINE_JOB_SCHEDULE_TIME_UTC_PLACEHOLDER to the placeholder
  resolution map in local execution. Timestamps are generated as
  timezone-aware UTC in ISO 8601 format.

Signed-off-by: Shreeharsh Shinde <shindeshreeharsh157@gmail.com>
Copilot AI review requested due to automatic review settings May 22, 2026 14:46
@google-oss-prow google-oss-prow Bot requested review from droctothorpe and zazulam May 22, 2026 14:46
@google-oss-prow
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign mprahl for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@google-oss-prow
Copy link
Copy Markdown

Hi @shreeharshshinde. Thanks for your PR.

I'm waiting for a kubeflow member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds support for additional local KFP placeholders, including pipeline job resource name and UTC timestamps for create/schedule time, with accompanying unit tests.

Changes:

  • Add new placeholder mappings for pipeline job resource name and UTC create/schedule timestamps.
  • Add unit tests to cover the new placeholder keys and validate timestamp formatting.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
sdk/python/kfp/local/placeholder_utils.py Adds placeholder mappings for pipeline job resource name and UTC create/schedule timestamp values.
sdk/python/kfp/local/placeholder_utils_test.py Adds tests for the new placeholders, including regex validation for UTC timestamp formats.

Comment on lines +364 to +384
@@ -369,8 +374,14 @@ def resolve_individual_placeholder(
json.dumps(executor_input_dict),
dsl.PIPELINE_JOB_NAME_PLACEHOLDER:
pipeline_resource_name,
dsl.PIPELINE_JOB_RESOURCE_NAME_PLACEHOLDER:
pipeline_resource_name,
dsl.PIPELINE_JOB_ID_PLACEHOLDER:
pipeline_job_id,
dsl.PIPELINE_JOB_CREATE_TIME_UTC_PLACEHOLDER:
utc_timestamp,
dsl.PIPELINE_JOB_SCHEDULE_TIME_UTC_PLACEHOLDER:
utc_timestamp,
Comment on lines +300 to +314
def test_pipeline_job_create_time_utc_placeholder(self):
"""Test that PIPELINE_JOB_CREATE_TIME_UTC_PLACEHOLDER is replaced with a valid UTC timestamp."""
actual = placeholder_utils.resolve_individual_placeholder(
element='{{$.pipeline_job_create_time_utc}}',
executor_input_dict=EXECUTOR_INPUT_DICT,
pipeline_resource_name='my-pipeline-2023-10-10-13-32-59-420710',
task_resource_name='comp',
pipeline_root='/foo/bar/my-pipeline-2023-10-10-13-32-59-420710',
pipeline_job_id='123456789',
pipeline_task_id='987654321',
)
# Verify that the result is a non-empty string in ISO 8601 format (YYYY-MM-DDTHH:MM:SS.sssZ)
import re
iso8601_pattern = r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z'
self.assertRegex(actual, iso8601_pattern)
Comment on lines +316 to +330
def test_pipeline_job_schedule_time_utc_placeholder(self):
"""Test that PIPELINE_JOB_SCHEDULE_TIME_UTC_PLACEHOLDER is replaced with a valid UTC timestamp."""
actual = placeholder_utils.resolve_individual_placeholder(
element='{{$.pipeline_job_schedule_time_utc}}',
executor_input_dict=EXECUTOR_INPUT_DICT,
pipeline_resource_name='my-pipeline-2023-10-10-13-32-59-420710',
task_resource_name='comp',
pipeline_root='/foo/bar/my-pipeline-2023-10-10-13-32-59-420710',
pipeline_job_id='123456789',
pipeline_task_id='987654321',
)
# Verify that the result is a non-empty string in ISO 8601 format (YYYY-MM-DDTHH:MM:SS.sssZ)
import re
iso8601_pattern = r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z'
self.assertRegex(actual, iso8601_pattern)
Ensure consistent timestamp values across different placeholders by
passing a single  through the resolution hierarchy.
Previously, individual resolution functions generated their own
timestamps, which could lead to discrepancies between related
placeholders.

Updated , ,
, and
 to accept  as an
argument. Added corresponding unit tests to verify timestamp
consistency.fix(local): resolve missing pipeline job placeholders at runtime

  Add PIPELINE_JOB_RESOURCE_NAME_PLACEHOLDER,
  PIPELINE_JOB_CREATE_TIME_UTC_PLACEHOLDER, and
  PIPELINE_JOB_SCHEDULE_TIME_UTC_PLACEHOLDER to the placeholder
  resolution map in local execution. Timestamps are generated as
  timezone-aware UTC in ISO 8601 format.

Signed-off-by: Shreeharsh Shinde <shindeshreeharsh157@gmail.com>
@shreeharshshinde
Copy link
Copy Markdown
Author

All three Copilot comments were valid and are now fixed:

High — timestamp stability: utc_timestamp is now generated once in replace_placeholders
and passed down through resolve_self_references_in_executor_input,
recursively_resolve_json_dict_placeholders, and resolve_individual_placeholder as a
parameter. Every placeholder resolution within the same local run sees the same
timestamp. All three functions have utc_timestamp='' as a default so existing callers
outside replace_placeholders aren't broken.

Low — import re inside test method: Moved to module scope alongside the new import
datetime.

Medium — regex not anchored / no same-value assertion: Pattern is now ^...$.
test_pipeline_job_create_time_utc_placeholder now resolves both create_time and
schedule_time with the same utc_timestamp and asserts actual_create == actual_schedule,
directly testing the stability contract.

@shreeharshshinde shreeharshshinde requested a review from Copilot May 22, 2026 14:57
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

import datetime
import json
import os
import re
Comment on lines 47 to +49
unique_task_id = make_random_id()
utc_timestamp = datetime.datetime.now(
datetime.timezone.utc).strftime('%Y-%m-%dT%H:%M:%S.%fZ')
Comment on lines +387 to +390
dsl.PIPELINE_JOB_CREATE_TIME_UTC_PLACEHOLDER:
utc_timestamp,
dsl.PIPELINE_JOB_SCHEDULE_TIME_UTC_PLACEHOLDER:
utc_timestamp,
Comment on lines 381 to +384
dsl.PIPELINE_JOB_NAME_PLACEHOLDER:
pipeline_resource_name,
dsl.PIPELINE_JOB_RESOURCE_NAME_PLACEHOLDER:
pipeline_resource_name,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[sdk] kfp.dsl placeholders not getting replaced at runtime (v2)

2 participants