Dashboard

Component Invocation Report To Pages

Pipeline for converting invocation reports to Pages with encoded ID transformation and markdown

Raw
Revised:
2026-04-22
Revision:
2
Related Notes:
Component - Invocation Graph View, Component - Markdown Visualizations, Component - Workflow API

Workflow Invocation Reports to Pages: Architecture Overview

Summary

Galaxy allows users to convert workflow invocation reports into Pages. This document traces the full pipeline from user action through markdown transformation to Page storage, with particular focus on the ID encoding/decoding lifecycle.

User Entry Point

A user viewing an invocation report clicks “Edit” (client/src/components/Workflow/InvocationReport.vue:66), which navigates to:

/pages/create?invocation_id={encoded_id}

The router (client/src/entry/analysis/router.js:522-527) passes invocation_id as a prop to PageForm.

Frontend Flow

client/src/components/PageDisplay/PageForm.vue:48-137

When invocationId is provided, PageForm fetches the invocation report:

GET /api/invocations/{invocation_id}/report

The response includes an invocation_markdown field containing Galaxy-flavored markdown with encoded IDs. The form pre-fills title, slug, and content. On submit, it POSTs to /api/pages with the invocation_markdown as content.

Backend Report Generation

The report generation pipeline involves three sequential transformations of the markdown.

Step 1: Populate Invocation Context

lib/galaxy/managers/markdown_util.py:997-1048populate_invocation_markdown()

Converts abstract workflow markdown into invocation-specific markdown by injecting the invocation ID:

  • output=nameinvocation_id={id}, output=name
  • input=nameinvocation_id={id}, input=name
  • step=nameinvocation_id={id}, step=name

ID format at this stage: decoded numeric (from invocation.id).

Step 2: Resolve Abstract References

lib/galaxy/managers/markdown_util.py:1051-1186resolve_invocation_markdown()

Replaces abstract workflow references with actual executed object IDs:

  • output=namehistory_dataset_id={actual_dataset_id}
  • input=namehistory_dataset_id={actual_input_id}
  • step=namejob_id={actual_job_id}
  • invocation_outputs(...) → expanded into individual history_dataset_display directives

ID format at this stage: decoded numeric (from resolved DB objects).

Step 3: Encode for Export

lib/galaxy/managers/markdown_util.py:651-669ready_galaxy_markdown_for_export()

Converts decoded numeric IDs to encoded IDs for external consumption. Also populates extra rendering metadata (dataset names, types, peek data).

ID format at this stage: encoded (via trans.security.encode_id()).

Call Chain

API: GET /api/invocations/{id}/report
  → services/invocations.py:161  show_invocation_report()
    → managers/workflows.py:430  get_invocation_report()
      → workflow/reports/__init__.py:7  generate_report()
        → workflow/reports/generators/__init__.py:38  generate_report_json()
          → _generate_internal_markdown()        [decoded IDs]
            → populate_invocation_markdown()      [decoded IDs]
            → resolve_invocation_markdown()       [decoded IDs]
          → ready_galaxy_markdown_for_export()    [encoded IDs]
        → returns { invocation_markdown: "..." }  [encoded IDs]

Page Creation

Frontend Submission

PageForm POSTs to /api/pages with:

{
    "title": "...",
    "slug": "...",
    "content_format": "markdown",
    "content": "<invocation_markdown with encoded IDs>"
}

Backend Page Creation

lib/galaxy/managers/pages.py:251-289create_page()

Two code paths exist:

  1. With invocation_id in payload (server-side generation): Fetches the invocation report directly, extracts the markdown content. This path exists but the current frontend flow uses the client-side approach instead (fetches report first, sends content).

  2. With content in payload (client-side content): Uses the content as-is, passes through rewrite_content_for_import().

Both paths converge at:

lib/galaxy/managers/pages.py:348-366rewrite_content_for_import()

For markdown content, calls ready_galaxy_markdown_for_import() which converts encoded IDs → decoded numeric IDs for database storage.

lib/galaxy/managers/markdown_util.py:112-139ready_galaxy_markdown_for_import()

Pattern: ENCODED_ID_PATTERN = r"(history_dataset_id|history_dataset_collection_id|...)=([a-z0-9]+)"

Applies trans.security.decode_id() to each matched ID.

Page Display

When a Page is displayed, rewrite_content_for_export() (pages.py:368-385) calls ready_galaxy_markdown_for_export() to:

  • Re-encode IDs for external links
  • Populate rendering metadata (dataset names, types, peek content)
  • Expand embedded directives

ID Format Lifecycle

StageLocationID FormatExample
Invocation in DBmodel.WorkflowInvocationDecoded numericid=12345
populate_invocation_markdownmarkdown_util.py:1034Decodedinvocation_id=12345
resolve_invocation_markdownmarkdown_util.py:1179Decodedhistory_dataset_id=5678
ready_galaxy_markdown_for_exportmarkdown_util.py:668Encodedhistory_dataset_id=abc456
API response to frontendworkflows.py:1559Encodedinvocation_markdown: "..."
Frontend POST to /api/pagesPageForm.vue:106EncodedPayload content
ready_galaxy_markdown_for_importmarkdown_util.py:124Decodedhistory_dataset_id=5678
Stored in PageRevision.contentpages.py:282DecodedDB storage
Page display (export)pages.py:377Encodedready_galaxy_markdown_for_export()

The full cycle is: decoded → encoded → (frontend) → encoded → decoded → (stored) → encoded → (displayed).

Key Regex Patterns

lib/galaxy/managers/markdown_util.py:68-92

UNENCODED_ID_PATTERN = re.compile(
    r"(history_id|workflow_id|history_dataset_id|history_dataset_collection_id|"
    r"job_id|implicit_collection_jobs_id|invocation_id)=([\d]+)"
)

ENCODED_ID_PATTERN = re.compile(
    r"(history_id|workflow_id|history_dataset_id|history_dataset_collection_id|"
    r"job_id|implicit_collection_jobs_id|invocation_id)=([a-z0-9]+)"
)

These patterns drive the import/export transformations and define which directive arguments are treated as IDs.

File Reference

PurposeFileLines
Frontend triggerclient/src/components/Workflow/InvocationReport.vue49-71
Frontend routeclient/src/entry/analysis/router.js522-527
Frontend formclient/src/components/PageDisplay/PageForm.vue48-137
Report API endpointlib/galaxy/webapps/galaxy/api/workflows.py1554-1577
Report servicelib/galaxy/webapps/galaxy/services/invocations.py161-163
Report generationlib/galaxy/managers/workflows.py430-449
Report pluginlib/galaxy/workflow/reports/__init__.py7-18
Markdown generatorlib/galaxy/workflow/reports/generators/__init__.py38-78
Populate invocationlib/galaxy/managers/markdown_util.py997-1048
Resolve invocationlib/galaxy/managers/markdown_util.py1051-1186
Export markdownlib/galaxy/managers/markdown_util.py651-669
Import markdownlib/galaxy/managers/markdown_util.py112-139
Page creationlib/galaxy/managers/pages.py251-289
Content importlib/galaxy/managers/pages.py348-366
Content exportlib/galaxy/managers/pages.py368-385
ID patternslib/galaxy/managers/markdown_util.py68-92

Incoming References (3)