{"id":18952263,"url":"https://github.com/step-security/dynamic-uses","last_synced_at":"2026-03-19T07:19:20.894Z","repository":{"id":247781944,"uuid":"822517202","full_name":"step-security/dynamic-uses","owner":"step-security","description":"Dynamically resolve and use another GitHub action","archived":false,"fork":false,"pushed_at":"2025-08-08T15:34:37.000Z","size":29,"stargazers_count":0,"open_issues_count":6,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-08T17:37:29.074Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/step-security.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-01T09:52:27.000Z","updated_at":"2024-07-03T13:52:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"a3e337d2-0672-4f66-9f50-2c2522ab5a1f","html_url":"https://github.com/step-security/dynamic-uses","commit_stats":null,"previous_names":["step-security/dynamic-uses"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/step-security/dynamic-uses","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/step-security%2Fdynamic-uses","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/step-security%2Fdynamic-uses/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/step-security%2Fdynamic-uses/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/step-security%2Fdynamic-uses/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/step-security","download_url":"https://codeload.github.com/step-security/dynamic-uses/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/step-security%2Fdynamic-uses/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28815141,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T12:25:15.069Z","status":"ssl_error","status_checked_at":"2026-01-27T12:25:05.297Z","response_time":168,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T13:32:21.305Z","updated_at":"2026-01-27T14:34:39.500Z","avatar_url":"https://github.com/step-security.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# dynamic-uses\n\nThis action allows you to dynamically resolve and use other GitHub actions, despite `uses` [not supporting](https://github.com/actions/runner/issues/895) expression contexts like `inputs`, `github` or `env`.\n\nThis can be useful if you are authoring multiple dependent actions within a repo and need to be able to test them dynamically AND use them from outside the repo.\n\n## Usage\n\nGiven a step like so:\n\n```yaml\n- uses: actions/setup-node@v3\n  with:\n    node-version: 18\n```\n\nIf you want your `uses` to be dynamic you can do:\n\n```yaml\n- uses: step-security/dynamic-uses@v1\n  with:\n    # now you can use expressions 🥳\n    uses: actions/setup-node@${{ inputs.version }}\n    # the `with` needs to be converted to a valid json string\n    with: '{ \"node-version\": 18 }'\n```\n\n## Why would I want to do this?\n\nMaybe you don't, but there are legitimate use cases 🙂. For example, suppose `my-cool-org/repo` has a couple reusable actions that could either be used within the repo or from other repos:\n\n**actions/cleanup/action.yml** - JavaScript action, details are irrelevant\n\n**actions/deploy/action.yml** - Composite action:\n\n```yaml\nname: Deploy the stuff\ninputs:\n  stuffToDeploy:\n    description: The stuff\nsteps:\n  - shell: bash\n    run: 'some-deploy-command \"${{ inputs.stuffToDeploy }}\"'\n  - uses: my-cool-org/repo/actions/cleanup@v3\n    with:\n      stuffToCleanUp: ${{ inputs.stuffToDeploy }}\n```\n\nBecause the `uses` is hardcoded, it will always use `cleanup@v3`. This makes it challenging to test how `deploy` will work with a new version of `cleanup`, as you have to create and trigger one-off workflows to validate a new version before it lands. Ideally you could `use` a path instead, but that only works for workflows that have checked out `my-cool-org/repo`; the `deploy` action is much harder to reuse if you have to do that (i.e. imagine these actions are used by various other repos in the `my-cool-org` org).\n\nTaking our example above, we can make it work however we need to with `dynamic-uses`:\n\n```yaml\n- uses: step-security/dynamic-uses@v1\n  env:\n    action_ref: ${{ github.action_ref }}\n  with:\n    # ensure we use the right version:\n    #  - within this repo, we want the `sha`\n    #  - from outside the repo, we want the `action_ref`\n    #    (we pass it through env, otherwise it picks up `v1` from `step-security/dynamic-uses@v1`)\n    uses: my-cool-org/repo/actions/cleanup@${{ github.repo == 'my-cool-org/repo' \u0026\u0026 github.sha || env.action_ref }}\n    with: '{ \"stuffToCleanUp\": \"${{ inputs.stuffToDeploy }}\" }'\n```\n\n## How does it work?\n\nIt turns out it's actually [pretty simple](./action.yml). Basically we have a composite action that generates another composite action based on the inputs, and then runs it.\n\nBecause the action is referenced by path, it satisfies the parser. By the time it's ready to execute that step, the action file exists and is ready to run 😅\n\n## Gotchas/limitations\n\n- The `with` inputs to the action need to be converted to a single JSON object string (see examples above)\n- Any outputs from the action will be serialized into a single `outputs` JSON object string. You can then access things using helpers like `fromJSON`, e.g. `fromJSON(steps.foo.outputs.outputs).something`\n\n## License\n\nThe scripts and documentation in this project are released under the [ISC License](./LICENSE.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstep-security%2Fdynamic-uses","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstep-security%2Fdynamic-uses","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstep-security%2Fdynamic-uses/lists"}