0

I am trying to build my reusable workflow in such a way anyone in my team can hook up with it, pass the variable that it needs, and the workflow decides what to do according to input received. The problem I am having comes when within such workflow, I want to call another one by using a received input. To go into details, my workflow receives as input:

inputs:
  service:
    description: 'The name of the service'
    required: false
    type: string

within one of its job I am trying to do the following:

  call-next-workflow:
    name: Run Test 
    uses: "./.github/workflows/${{inputs.service}}.yml"

unfortunately github complains saying:

"./.github/workflows/${{inputs.service}}.yml" : failed to fetch workflow: workflow was not found.

Is there a way to use my parameter into the uses part, needed to call the next workflow?

Tarta
  • 1,729
  • 1
  • 29
  • 63
  • 1
    According to this relevant GHA [issue](https://github.com/orgs/community/discussions/25246)'s [answer](https://github.com/orgs/community/discussions/25246#discussioncomment-3247073), "**In order to enact policies like only using actions defined in the org or repo we can’t allow actions to dynamically change at runtime. So using any sort of dynamic value in `uses` is not something we will be able to support.**. – Azeem Mar 13 '23 at 16:26

2 Answers2

1

The problem is that the uses path must be static and cannot be dynamic.

As a workaround, you could create a proxy workflow, which references each of the possible services.

on: workflow_call
inputs:
  service:
    required: true
    type: string

jobs:
  service_a:
    if: inputs.service == 'service A'
    uses: ".github/workflows/service_a.yaml@main"
  service_b:
    if: inputs.service == 'service B'
    uses: ".github/workflows/service_b.yaml@main"
  service_c:
    if: inputs.service == 'service C'
    uses: ".github/workflows/service_c.yaml@main"

I appreciate that this does not have the same level of flexibility as a dynamic uses path.

Glen Thomas
  • 10,190
  • 5
  • 33
  • 65
  • understood! Indeed I was looking for a bit more flexibility than listing all possible scenarios in a static way but if this is the only way forward then nothing much to do about it! Thank you! – Tarta Mar 17 '23 at 09:03
0

As pointed out uses accepts static path, but that doesn't mean you can't have dynamic content inside that action path. You can create a proxy workflow that invokes your actual workflow. Before invoking this proxy workflow you can modify its content in another job to have the dynamic effect.

For your example you can create a prepare job:

prepare:
  runs-on: ubuntu-latest
  env:
    DYNAMIC_WORKFLOW: .github/workflows/dynamic.yml
  steps:
  - name: Setup dynamic workflow
    uses: actions/github-script@v6
    with:
      script: |
        const path = require('path');
        const fs = require('fs/promises');
        const workflow = {
          name: "Dynamic workflow",
          on: {
            workflow_call: {}
          },
          jobs: {
            actual-call-next-workflow: {
              uses: "./.github/workflows/${{inputs.service}}.yml",
            }
          }
        };
        await fs.writeFile(${{ env.DYNAMIC_WORKFLOW }}, JSON.stringify(workflow));

And in the next job to prepare, run this dynamic reusable workflow:

call-next-workflow:
  needs: prepare
  uses: ".github/workflows/dynamic.yml"
Soumya Mahunt
  • 2,148
  • 12
  • 30