admin管理员组文章数量:1390924
I'm using concurrency in my GitHub Actions to limit all workflows to one simultaneous run per workflow, per ref.
This ensures that only the latest push to a branch or pull request runs per workflow, saving both time and money.
This setup worked perfectly, until I tried using workflow_call
. The issue arises because my concurrency group naming, which relies on ${{ github.workflow }}-${{ github.ref }}
, doesn't work as expected with workflow_call
events.
The problem is that ${{ github.workflow }}
in the callee workflow inherits the name of the caller workflow (similar to how permissions work). This leads to a naming conflict, causing the callee to fail immediately. I can't seem to find a way to get the filename inside a workflow called by workflow_call
, since according to the docs the callee inherits everything from the caller.
I need a solution that keeps the concurrency group label dynamic. ${{ github.workflow }}
was ideal because workflow filenames are unique in the workflows
folder, ensuring no accidental duplicates from other team members. I want to maintain this level of "idiot-proofing" while resolving the conflict with workflow_call
.
Here is my setup:
deploy.web.yaml
name: "deploy / web"
on:
workflow_dispatch:
workflow_call:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
staging:
runs-on: ubuntu-latest
steps:
- run: echo "Web deployment to staging not configured yet"
release.yaml
name: "release"
on:
push:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
metadata:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v4
web:
needs: [metadata]
uses: ./.github/workflows/deploy.web.yaml
EXPECTED
The release.yaml
workflow should and call deploy.web.yaml
successfully. If release.yaml
is then called again while the previous call is still running it should cancel the oldest one and proceed with the newest.
ACTUALITY
deploy.web.yaml
fails immediately on the first call with this error:
Canceling since a deadlock for concurrency group 'release-refs/heads/main' was detected between 'top level workflow' and 'api'
NOTE
Before answering this please be know that:
I am aware that I can just name the workflows hard coded, e.g.
deploy-web-${{ github.ref }}
, but this would go against the "idiot-proofing" I talked about before. Not to mention it would be very annoying having every concurrency group be dynamic except for the ones withworkflow_call
, which would always need to be hard coded.I am also aware I can set the concurrency at the
job
level in therelease.yaml
workflow, like this:
jobs:
web:
concurrency:
group: ${{ github.workflow }}-web-${{ github.ref }}
cancel-in-progress: true
uses: ./.github/workflows/deploy.web.yaml
This however, does not define concurrency at the workflow
level and would mean If I were to call the workflow by another event, say workflow_dispatch
, it would not have concurrency protection. Not to mention we also be hard coding the name for the group once again.
Hopefully there is a reasonable solution for this within the context of what I am looking for!
I'm using concurrency in my GitHub Actions to limit all workflows to one simultaneous run per workflow, per ref.
This ensures that only the latest push to a branch or pull request runs per workflow, saving both time and money.
This setup worked perfectly, until I tried using workflow_call
. The issue arises because my concurrency group naming, which relies on ${{ github.workflow }}-${{ github.ref }}
, doesn't work as expected with workflow_call
events.
The problem is that ${{ github.workflow }}
in the callee workflow inherits the name of the caller workflow (similar to how permissions work). This leads to a naming conflict, causing the callee to fail immediately. I can't seem to find a way to get the filename inside a workflow called by workflow_call
, since according to the docs the callee inherits everything from the caller.
I need a solution that keeps the concurrency group label dynamic. ${{ github.workflow }}
was ideal because workflow filenames are unique in the workflows
folder, ensuring no accidental duplicates from other team members. I want to maintain this level of "idiot-proofing" while resolving the conflict with workflow_call
.
Here is my setup:
deploy.web.yaml
name: "deploy / web"
on:
workflow_dispatch:
workflow_call:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
staging:
runs-on: ubuntu-latest
steps:
- run: echo "Web deployment to staging not configured yet"
release.yaml
name: "release"
on:
push:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
metadata:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@v4
web:
needs: [metadata]
uses: ./.github/workflows/deploy.web.yaml
EXPECTED
The release.yaml
workflow should and call deploy.web.yaml
successfully. If release.yaml
is then called again while the previous call is still running it should cancel the oldest one and proceed with the newest.
ACTUALITY
deploy.web.yaml
fails immediately on the first call with this error:
Canceling since a deadlock for concurrency group 'release-refs/heads/main' was detected between 'top level workflow' and 'api'
NOTE
Before answering this please be know that:
I am aware that I can just name the workflows hard coded, e.g.
deploy-web-${{ github.ref }}
, but this would go against the "idiot-proofing" I talked about before. Not to mention it would be very annoying having every concurrency group be dynamic except for the ones withworkflow_call
, which would always need to be hard coded.I am also aware I can set the concurrency at the
job
level in therelease.yaml
workflow, like this:
jobs:
web:
concurrency:
group: ${{ github.workflow }}-web-${{ github.ref }}
cancel-in-progress: true
uses: ./.github/workflows/deploy.web.yaml
This however, does not define concurrency at the workflow
level and would mean If I were to call the workflow by another event, say workflow_dispatch
, it would not have concurrency protection. Not to mention we also be hard coding the name for the group once again.
Hopefully there is a reasonable solution for this within the context of what I am looking for!
Share Improve this question edited Mar 16 at 0:18 dy0gu asked Mar 15 at 23:48 dy0gudy0gu 4321 gold badge4 silver badges15 bronze badges 5 |1 Answer
Reset to default 1TLDR
- Unfortunately (AFAICT) hardcoded concurrency groups is the only way
${{ github.workflow_ref }}-${{ github.ref }}
seems to be the most error-proof combination I've found
Uniqueness
${{ github.workflow }} was ideal because workflow filenames are unique in the workflows folder
As per documentation (emphasis mine):
The name of the workflow. If the workflow file doesn't specify a name, the value of this property is the full path of the workflow file in the repository.
So, if anyone names their workflow name: A
and another name: A
it would be a collision. On the other hand ${{ github.workflow_ref }}
has this property, as it's a path, no matter the name.
Additionally (unlike what might have seemed in my comment), you would need ${{ github.ref }}
as it refers to the ref
tirggering the worklow (it might be refs/heads/<branch_name>
if this is the trigger). ${{ github.workflow_ref }}
ref
refers to the one which hosts the file (usually main
).
In your case it shouldn't matter as the workflow is set to main
, but in some other branch-based workflow it might (so I'd deem it less "automatic" as per your jargon).
Caller vs callee
This seems to be exactly what I was looking for. Only thing I still need is for it to not get overwritten by the caller workflow in workflow_call
Unfortunately it isn't as there is no way to differentiate between the two via available contexts
to the concurrency
field.
There seems to be a way to distinguish between caller and the calle as described here but for OIDC claim tokens, for example:
{
"workflow_ref": "/repo/.github/workflows/top-level-workflow.yml@refs/heads/main",
"job_workflow_ref": "2/repo2/.github/workflows/reusable-workflow-3.yml@v1",
}
where workflow_ref
is akin to the one mentioned above and job_workflow_ref
is the callee reference at the end of the chain (which would suffice in your case).
Other things tried
Just to be sure, I've also checked in a separate repo specifying the reusable workflow via "local" (as yours ./.github/workflows/deploy.web.yaml
) and "global" references (octo-/example-repo/.github/workflows/reusable-workflow.yml@main
), no difference
本文标签:
版权声明:本文标题:continuous integration - Using workflow filename in concurrency group for workflows started by workflow_call in GitHub Actions - 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744601070a2615068.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
concurrency
object in the calling workflow, no? – Benjamin W. Commented Mar 15 at 23:48workflow_call
. Do you know what the behavior is in that case? I can't seem to find it in the documentation, and I also can't test it right now unfortunately. If it works withworkflow_call
it's the perfect solution! – dy0gu Commented Mar 17 at 1:20github.workflow_ref
more precise as my comment above is misleading after reading it again (that's why I deleted it). – Szymon Maszke Commented Mar 17 at 13:04