Skip to content

Commit

Permalink
Comment On Forks Instead Writes To Artifact (#322)
Browse files Browse the repository at this point in the history
* added line

* upload as artifact when comment fails

* try relative file path

* log paths to info

* use absolute path

* also upload PR number

* needs to be issue_number

* artifactOnFailure boolean to avoid cyclical uploads

* change file

* add some docs

---------

Co-authored-by: Jacob Bolda <[email protected]>
  • Loading branch information
supitscaro and jbolda authored Jun 25, 2024
1 parent 8735759 commit e5d2be5
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 26 deletions.
5 changes: 5 additions & 0 deletions .changes/comment-error-to-artifact.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"action": patch
---

On comment post error, upload the content instead as an artifact. This prevents the workflow from failing on a fork, and allows another workflow with permissions to handle the work from there.
2 changes: 1 addition & 1 deletion .github/workflows/comment-on-forks.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Covector Comment
name: covector comment on forks

on:
workflow_run:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-on-pr.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: covector
name: covector status
on: pull_request

jobs:
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ Below is a list of all of the packages within this repository. The usage and doc
| [@covector/command](./packages/command) | [![npm](https://img.shields.io/npm/v/@covector/command?style=for-the-badge)](https://www.npmjs.com/package/@covector/command) | [./packages/command/CHANGELOG.md](https://github.com/jbolda/covector/blob/main/packages/command/CHANGELOG.md) |
| [@covector/files](./packages/files) | [![npm](https://img.shields.io/npm/v/@covector/files?style=for-the-badge)](https://www.npmjs.com/package/@covector/files) | [./packages/files/CHANGELOG.md](https://github.com/jbolda/covector/blob/main/packages/files/CHANGELOG.md) |


## Prior Art

We drew on inspiration from [changesets](https://github.com/atlassian/changesets) which specifically focuses on the npm ecosystem with the expectation to publish to [npmjs.com](https://www.npmjs.com/). We had a need for much greater flexibility, primarily around additional languages, which changesets wasn't looking to handle. You may notice some similarities around the markdown based change files, and it begins to diverge from there. Since we started the codebase from scratch, it also opened the door for incredibly flexible and unique publishing schemes, deep changelogs, and the ability to publish to any "target" with any "asset" (such as publishing a website, a github action or a vscode extension even!).
Expand Down
13 changes: 7 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions packages/action/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,39 @@ Besides these static outputs, we also supply dynamic outputs for each of your pa
Outputs will generally be specified in the [action.yml](./action.yml), but since these are dynamic, it is not possible. See the [docs noting this is an optional required](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#outputs).

> If you don't declare an output in your action metadata file, you can still set outputs and use them in a workflow.

## Comments On Forks

The action runs in a reduced-permission environment on forks which will cause an API call to add a comment to fail. To work around this, with `comment: true` specified, it will upload the comment content as an artifact to the workflow if it fails. With the following additional workflow, it will pick up that workflow completion and post the comment as `workflow_run` has normal repository permissions.

```yml
name: Covector Comment
on:
workflow_run:
workflows: [covector status] # the `name` of the workflow run on `pull_request` running `status` with `comment: true`
types:
- completed

# note all other permissions are set to none if not specified
permissions:
# to read the action artifacts
actions: read
# to write the comment
pull-requests: write
# note that these set the permissions for `secrets.GITHUB_TOKEN`
# if you plan to use your own token, use `permissions: {}` instead
# to completely remove all default permissions for added security

jobs:
download:
runs-on: ubuntu-latest
if: github.event.workflow_run.conclusion == 'success' &&
(github.event.workflow_run.head_repository.full_name != github.repository || github.actor == 'dependabot[bot]')
steps:
- name: covector status
uses: jbolda/covector/packages/action@covector-v0
with:
token: ${{ secrets.GITHUB_TOKEN }}
command: "status"
```
1 change: 1 addition & 0 deletions packages/action/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"clean": "echo noop"
},
"dependencies": {
"@actions/artifact": "^2.1.7",
"@actions/core": "^1.10.1",
"@actions/github": "^5.1.1",
"effection": "^2.0.6",
Expand Down
69 changes: 52 additions & 17 deletions packages/action/src/comment/postGithubComment.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { GitHub } from "@actions/github/lib/utils";
import { DefaultArtifactClient } from "@actions/artifact";
import fs from "node:fs/promises";
import path from "node:path";
import type { GitHub } from "@actions/github/lib/utils";
import { Operation } from "effection";
import { Logger } from "@covector/types";

Expand All @@ -9,13 +12,15 @@ export function* postGithubComment({
repo,
owner,
prNumber: issue_number,
artifactOnFailure = true,
}: {
logger: Logger;
comment: string;
octokit: InstanceType<typeof GitHub>;
repo: string;
owner: string;
prNumber: number;
artifactOnFailure?: boolean;
}): Operation<void> {
const tag = "<!-- Covector Action -->\n";
const body = tag + comment;
Expand All @@ -30,21 +35,51 @@ export function* postGithubComment({
comment.body.includes(tag)
);

if (previousComment) {
logger.info("Updating comment in pull request.");
yield octokit.rest.issues.updateComment({
owner,
repo,
comment_id: previousComment.id,
body,
});
} else {
logger.info("Posting comment in pull request.");
yield octokit.rest.issues.createComment({
owner,
repo,
issue_number,
body,
});
// this can fail if the token doesn't have permissions
try {
if (previousComment) {
logger.info("Updating comment in pull request.");
yield octokit.rest.issues.updateComment({
owner,
repo,
comment_id: previousComment.id,
body,
});
} else {
logger.info("Posting comment in pull request.");
yield octokit.rest.issues.createComment({
owner,
repo,
issue_number,
body,
});
}
} catch (error) {
if (artifactOnFailure) {
logger.error("Posting comment failed, creating artifact instead.");
const artifactRoot = process.env.RUNNER_TEMP ?? "..";

const artifactFilename = "./covector-comment.md";
const artifactAbsolutePath = path.join(artifactRoot, artifactFilename);
logger.debug(`Writing comment body to ${artifactAbsolutePath}`);
yield fs.writeFile(artifactAbsolutePath, body);

const artifactPRNumber = "./covector-prNumber.md";
const prNumberAbsolutePath = path.join(artifactRoot, artifactPRNumber);
yield fs.writeFile(prNumberAbsolutePath, issue_number.toString());

const artifact = new DefaultArtifactClient();
logger.debug(`Uploading comment from ${artifactAbsolutePath}`);
yield artifact.uploadArtifact(
"covector-comment",
[artifactAbsolutePath, prNumberAbsolutePath],
artifactRoot,
{
retentionDays: 1,
}
);
} else {
logger.fatal(`Posting comment failed.`);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,6 @@ export function* postGithubCommentFromArtifact({
repo,
owner,
prNumber,
artifactOnFailure: false,
});
}

0 comments on commit e5d2be5

Please sign in to comment.