ci.comment
The ci.comment function posts a comment on the pull request, or on the commit when the run has no pull request.
Give the comment a key and later runs update the same comment instead of adding a new one each time. Locally, the
comment is previewed on stderr and never posted.
Usage
ci.comment(body = "", key = "", behavior = "upsert", pr = 0, target = "auto", template = "", data = None)
Arguments
bodyThe comment text, as Markdown in a string. Required unless
templateis given, and it cannot be combined withtemplateordata, even when it is an empty string.key(Optional) A stable name for the comment. The comment carries a hidden marker built from the key, which later runs use to find it. Without a key, the call always creates a new comment.
behavior(Optional) What to do when a comment with the key already exists. The value
"upsert"(the default) updates it and creates one when none exists,"create"always adds a new comment, and"update"only changes a comment that already exists. The"update"behavior needs akey, because the key is how the comment is found. In CI,"update"fails when no comment with the key exists yet, and the local preview fails the same way.pr- (Optional) The pull request number to comment on, as an integer. It defaults to the current pull request.
target(Optional) Where the comment goes, as a string. The value
"auto"(the default) posts to the pull request when one is known and to a comment on the commit (ci.context.sha) otherwise. The value"pr"always posts to the pull request and fails when none is known. The value"commit"always posts a comment on the commit, even when the run has a pull request. Any other value fails with an argument error.template(Optional) The name of a template file to render into the comment body, instead of passing
body. It is a file name underci.templates.base_path, or an absolute path. There is no default template, sodataalways needs atemplate.data(Optional) A dict that becomes the template context. Keys are read in the template as
.key. Passingdatawithouttemplatefails with an argument error that saystemplate=is required.
Templates
A script can keep the layout of a comment in a template file and pass only the values:
- A call with
template=renders that file, withdataas the context. A call with onlybodyposts the text as written. - There is no configured default template. Every call that renders a template names it with
template=. - The name is resolved against
ci.templates.base_path. A relativebase_pathresolves against the Atmosbase_path. When no file has exactly that name, the name with a.mdsuffix is tried. - Templates use Go template syntax with the same functions as the built-in plan templates. The
datadict is the template context. - A key that the template reads but
datadoes not contain fails the render and names the key, so a typo does not post<no value>. - The
key,behavior,pr, andtargetarguments work the same with a rendered body.
See script report templates for the configuration.
Returns
A struct that describes the comment:
id- The identifier of the comment. A comment that was only previewed locally has a synthetic id that starts at 1.
url- A link to the comment, as a string. It is empty when the comment was only previewed locally.
created- A boolean that is
Truewhen the call created a new comment andFalsewhen it updated one. target- The place the comment landed, as a string:
"pr"or"commit". Withtarget = "auto"it tells you which one was chosen.
Behavior
- In CI, the comment is posted through the provider's API. A pull request comment needs
pull-requests: writeon GitHub Actions, and a commit comment needscontents: write. - A commit comment is attached to
ci.context.sha. It appears on the commit page and, for a commit that belongs to an open pull request, in that pull request's timeline. Keys work the same way, so a keyed commit comment is updated on the next run for the same commit. - A run with no pull request, such as a
push, comments on the commit with the defaulttarget = "auto". Underworkflow_runandpull_request_target, the pull request number comes from the event payload, so"auto"still finds the pull request. - Locally, the comment is previewed on stderr and never posted. The returned
urlis empty. - The body is masked before it leaves the process.
- Comments are opt-in. In CI the call is gated by
ci.comments.enabled, which is off by default. When it is off, the call warns, renders locally, and the script continues. - Under
pull_request_targetandworkflow_run, the comment is held only when the pull request comes from a fork (ci.context.pr.fork), unlessci.allow_unsafe_fork_executionistrue. A held call warns and renders locally instead. See the fork gate.
Examples
Keep one comment up to date
ci.comment("### Plan\n\n3 to add, 1 to change, 0 to destroy.", key = "plan")
Every run updates the same comment, so the pull request never collects a stack of stale ones.
Comment on a push
ci.comment("Deployed **" + ci.context.sha[:7] + "** to prod.", key = "deploy")
This needs no guard. On a pull request run it comments on the pull request. On a push run it comments on the commit.
Require a pull request
ci.comment("Preview ready.", key = "preview", target = "pr")
The call fails when the run has no pull request, which is useful when a missing pull request is a bug in the workflow.
Post to a specific pull request
result = ci.comment("Released in v1.4.0.", pr = 214)
ui.info("Posted " + result.url)
Always add a new comment
ci.comment("Rebased onto main.", behavior = "create")
Render a comment from a template
### Release {{ .version }}
Deployed to {{ .stack }}.
ci.comment(template = "release.md", data = {"version": "1.4.0", "stack": "prod"}, key = "release")
Errors
- An API error, a missing token, or a pull request number that does not exist fails the script. See errors.
- An unknown
behaviorortargetfails with an argument error that namesci.comment. - Passing
bodytogether withtemplateordata(an emptybodycounts), adatavalue that is not a dict, ordatawithouttemplatefails with an argument error. target = "pr"with no pull request fails with a pull-request-unknown error.- A template that does not exist fails the script with an error that names the resolved path and the value of
ci.templates.base_path. A template that reads a key missing fromdata, or that fails to render, fails the script.
Related
cidescribes the module and the shared behavior rules.- CI pull request comments configures the native comments that Atmos posts for commands.
ci.summarywrites to the job summary, which needs no pull request.