Streamlining GitHub Actions: Dynamic Inputs for Reusable Workflows and Engineering Intelligence
The GitHub Actions ecosystem is a cornerstone of modern CI/CD, enabling powerful automation through workflows. A recent discussion on the GitHub Community platform, initiated by user umarcor, highlights a critical limitation in how reusable workflows handle inputs, specifically the inability to pass dynamic JSON strings directly to the with arguments. This insight explores the problem, its implications for developer productivity and engineering intelligence tools, and the community-suggested workarounds.
The Challenge: Static Inputs for Dynamic Workflows
Reusable workflows are designed to promote modularity and reduce duplication, allowing developers to define common sets of steps or jobs that can be called from multiple places. The issue arises when trying to pass arguments to these reusable workflows dynamically. As umarcor demonstrates, while GitHub Actions supports parsing JSON strings for defining matrices within a job (e.g., fromJson(needs.matrix.outputs.matrix)), the same flexibility does not extend to the with block of a reusable workflow call.
When attempting to pass a JSON string, such as ${{ fromJson(github.event.inputs) }} or even a direct ${{ inputs }}, the workflow parser throws an error:
Unrecognized named-value: 'inputs'
Unexpected value '${{ fromJson(inputs) }}'
Unexpected type 'StringToken' encountered while reading 'uses-with value'. The type 'MappingToken' was expected.
This error clearly indicates that the with block expects a YAML mapping (MappingToken) – a literal key-value structure – rather than a dynamic string that could resolve to a mapping at runtime. This limitation forces developers to explicitly list each input, even when the input structure is already available as a JSON object, hindering the creation of truly flexible and data-driven workflows essential for advanced software project KPI tracking.
The Community's Feature Request: Dynamic StringToken Support
The core of umarcor's proposal is to allow the with arguments to accept a StringToken (a JSON string) that can be parsed into a MappingToken. This would enable scenarios where workflow inputs are generated programmatically or derived from other workflow steps, allowing for a more streamlined and less verbose configuration. For instance, a complex set of configuration parameters could be prepared as a JSON object in an earlier step and then passed directly to a reusable workflow, significantly simplifying the caller's YAML.
Current Workarounds for Dynamic Input Management
While the requested feature is not yet available, the community discussion and expert replies offer practical workarounds:
1. Explicitly List Each Input
The most straightforward, albeit verbose, solution is to explicitly map each input from the calling workflow to the reusable workflow's with block:
# dispatch.yml
on: workflow_dispatch:
inputs:
key:
required: true
type: string
submodules:
required: true
type: string
jobs:
dispatch:
uses: ./.github/workflows/common.yml
with:
key: ${{ inputs.key }}
submodules: ${{ inputs.submodules }}
This works but can become cumbersome for workflows with many inputs or when the input structure is dynamic.
2. Pass a Single JSON String and Parse Internally
A more flexible approach involves passing the entire dynamic configuration as a single JSON string input to the reusable workflow. The reusable workflow then uses fromJson() internally to access individual keys:
# Caller workflow
with:
config_json: ${{ toJson(inputs) }}
# Reusable workflow (common.yml)
on: workflow_call:
inputs:
config_json:
description: 'Dynamic configuration as JSON string.'
required: true
type: string
jobs:
# ...
steps:
- run: echo "Key value: ${{ fromJson(inputs.config_json).key }}"
This method centralizes the dynamic parsing within the reusable workflow, making the caller cleaner. It's a pragmatic compromise for managing complex, dynamic input structures, and can be valuable for collecting data points for kpi engineering metrics.
3. Programmatically Generate Caller YAML
For highly dynamic scenarios, some developers resort to generating the caller workflow's YAML file programmatically. This is similar to how complex matrices might be generated, ensuring the `with` block always conforms to the `MappingToken` requirement at the time of workflow definition.
Conclusion: Towards More Flexible Workflow Automation
The ability to pass dynamic JSON objects directly to reusable workflow with arguments would be a significant enhancement for GitHub Actions. It would empower developers to build more abstract, data-driven, and maintainable CI/CD pipelines, reducing boilerplate and increasing the agility of workflow development. Such a feature would directly contribute to more sophisticated engineering intelligence tools by enabling richer, context-aware automation and more efficient tracking of software project KPIs. The community's active engagement on this topic underscores its importance for the future of GitHub Actions and developer productivity.
