Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use composite action for issue creation #131

Closed
wants to merge 9 commits into from
Closed

Conversation

mre
Copy link
Member

@mre mre commented May 30, 2022

No description provided.

@mre mre force-pushed the composite-issue branch from 37eb346 to 22fd79c Compare May 30, 2022 22:52
@mre mre force-pushed the composite-issue branch from 22fd79c to 5886c61 Compare May 30, 2022 22:55
@polarathene
Copy link

You may want to also add micalevisk/find-last-issue to support the issue feature? (to handle updating an existing open issue)

I have looked into it myself for issue creation with peter-evans/create-issue-from-file to create or update an existing issue. It works well, see the linked discussion for a snippet example of the two used together.

@mre
Copy link
Member Author

mre commented Jul 3, 2022

You may want to also add micalevisk/find-last-issue to support the issue feature? (to handle updating an existing open issue)

Sorry, not sure I follow. create-issue-from-file already supports updating an existing issue. Did you mean that we could use find-last-issue to add a new comment to an existing issue? That would be what I had in mind actually. I thought create-issue-from-file could do that, but maybe I was wrong.
What I want is for the user to pass an optional issue number an the lychee-action would add a comment there. If no issue number was given, it would create a new issue.

@polarathene
Copy link

polarathene commented Jul 3, 2022

Did you mean that we could use find-last-issue to add a new comment to an existing issue?

No.

What I want is for the user to pass an optional issue number an the lychee-action would add a comment there. If no issue number was given, it would create a new issue.

What is the use of the comment? The author of create-issue-from-file has a similar action for managing comments (I use another action myself for creating and updating a comment on PRs).


  • create-issue-from-file will create an issue unless given an issue number to update.
  • find-last-issue provides a means to lookup the issue number of that created issue, instead of updating your workflow (temporarily?) to tell create-issue-form-file to update the existing issue and not create a new one.
  • This can additionally take the state of an issue into account as well, so that only an open issue is updated... Thus if you resolve the links reported and close the issue, a new one will be opened next time instead until that one is closed. Otherwise the issue will just have it's body content updated/replaced (no need to append comments?).

@mre
Copy link
Member Author

mre commented Jul 3, 2022

Gotcha.

If possible I'd like to keep the number of dependencies to other Github actions at a minimum.
This is to avoid additional maintenance overhead when these dependencies change or get deprecated.

I'd love to have the possibility to append a new comment to an existing issue. However this can be added
in a separate PR.
For now I'd like to merge the functionality in as is. Does it look good from your perspective @polarathene?
Would like to get an approval to be sure I didn't mess up.

Also, we should release this as part of version 2.0 of the extension to avoid any breaking changes.
(Otherwise two issues would be created in the worst case — one by the existing call to create-issue-from-file and one by the now built-in issue creator.)

@mre mre added the 2.0 label Jul 3, 2022
Copy link

@polarathene polarathene left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not reviewed workflows/{links,main}.yml which appear to be for your own testing of the action.

I realize the review is quite verbose, but hopefully worthwhile 😅 (I tried to make it more terse by collapsing less important details)

description: "summary output file path"
default: "lychee/out.md"
description: "Summary output file path"
default: "summary.md"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the working directory for this action is likely a git repo, and other steps in the job (using this composite as a single step) may also process content at this location. You should not write into it and instead prefer using a temporary location?

Suggested change
default: "summary.md"
default: "${{ runner.temp }}/summary.md"

https://docs.github.com/en/actions/learn-github-actions/contexts#runner-context

entrypoint.sh could also do the same (and maybe mkdir a sub-directory for lychee?).

required: false
fail:
description: "fail entire pipeline on error (i.e. when lychee exit code is not 0)"
description: "Fail entire pipeline on error (i.e. when lychee exit code is not 0)"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fail should be dropped. As should exit_code output (may still be relevant, see other review comment for step conditional).

#85 (comment)

default: 0.10.0
required: false
createIssue:
description: "Create Github issue if link check fails"
default: true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be opt-in.

I would not want issues being created by default when using this to lint PRs.

The only time it makes sense is for a scheduled recurring job to notify maintainers. When that is desired it should be looked up and opt-in, not occur by default which would be surprising for an action that supports other use-cases. Additionally it'd likely fail on PRs (from third-party contributors, due to running in an insecure context required permissions would be missing).

Suggested change
default: true
default: false

Comment on lines +32 to +44
issueTitle:
description: "Title of Github issue which will be created if link check fails"
default: Link Checker Report
required: false
issueLabels:
description: "Attach labels to Github issue"
default: links, report, automated issue
required: false
issueRepository:
description: 'The target GitHub repository for creating issues'
default: ${{ github.repository }}
issueNumber:
description: 'The issue number of an existing issue to update'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worthwhile for maintainers (beyond yourself) to grok this composite action easier if the scope of inputs is less vague.

A simple comment should help with that since these are all sub-inputs to the create-issue-from-file action and you're just forwarding them:

+  # These inputs only valid when `createIssue: true`
  issueTitle:
    description: "Title of Github issue which will be created if link check fails"
    default: Link Checker Report
    required: false
  issueLabels:
    description: "Attach labels to Github issue"
    default: links, report, automated issue
    required: false
  issueRepository:
    description: 'The target GitHub repository for creating issues'
    default: ${{ github.repository }}
  issueNumber:
    description: 'The issue number of an existing issue to update'

required: false
issueLabels:
description: "Attach labels to Github issue"
default: links, report, automated issue

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I'd rather not have an action add a bunch of labels polluting a projects own labels (a project I maintain has plenty already and these would be unwanted noise in the way of manual triage).

Especially if the action is not even using the labels for any purpose... that should be opt-in (no default, show the feature off in examples instead).

If you added the other action which can lookup an issue number by label (picks the issue result sorted by last updated), then something like this might be useful:

Suggested change
default: links, report, automated issue
default: ci-lychee

Otherwise avoid default labels, let the user choose labels that are relevant to their project for this feature.

@@ -46,6 +65,15 @@ runs:
INPUT_JOBSUMMARY: ${{ inputs.JOBSUMMARY }}
shell: bash

- if: inputs.CREATEISSUE && steps.lychee.outputs.exit_code != 0

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to check failure status and step outcome, rather than exit_code as was discussed here:

Suggested change
- if: inputs.CREATEISSUE && steps.lychee.outputs.exit_code != 0
- if: ${{ failure() && steps.lychee.outcome == 'failure' && inputs.createIssue }}

Remember this would involve lychee step dropping inputs.fail (doesn't serve a purpose) and outputs.exit_code (redundant?).


In saying that, exit_code does communicate two kind of failures:

  • 1: Generic failure.
  • 2: One or more links failed when checked.

And your issue creation is probably only interested in exit_code == 2 so that it has content worth reporting (Although perhaps you'd want to update/close the issue if a link failure was temporary and exit_code was 0 in a future run).

Presently you handle a related scenario that exit_code == 2 does not:

if [ ! -f "${LYCHEE_TMP}" ]; then
echo "No output. Check pipeline run to see if lychee panicked." > "${LYCHEE_TMP}"
fi

Ideally an output to communicate the link failure is more than exit_code == 2, so that the next action reacting to that has actual content to put into the body too.. This kind of fallback content probably isn't what you'd want to see? (unless this error prevents returning the exit_code of 2?)


`continue-on-error: true` (_I need to verify some information_)

Alternatively with steps.lychee.continue-on-error: true, the job would not exit early. I'm not sure how that applies in composite action however.

I need to check if failure() is still valid with that setting, or if only lychee.outcome == 'failure' should be checked due to lychee.conclusion == 'success' always being the case.

Suggested change
- if: inputs.CREATEISSUE && steps.lychee.outputs.exit_code != 0
- if: ${{ steps.lychee.outcome == 'failure' && steps.lychee.outputs.exit_code == 2 && inputs.createIssue }}

steps.lychee.outcome == 'failure' would be redundant then, if steps.lychee.outputs.exit_code == 2 was required 😅


Finally with consideration for other failures that could occur in the action.. (_I need to verify some information_)

You may want the workflow run to fail by not using continue-on-error: true. AFAIK workflow failures will send a notification to maintainers to be aware of... Thus exit_code == 2 should not fail the action step? (but retain an output to distinguish from checks with no failed links)

Bringing us closer to the condition you have used:

Suggested change
- if: inputs.CREATEISSUE && steps.lychee.outputs.exit_code != 0
- if: ${{ steps.lychee.outputs.exit_code == 2 && inputs.createIssue }}

I think, a workflow that has other steps involved unrelated to link checking should be in separate jobs, where they would not be affected and a failed status is fine then.

It's then the decision of if running create-issue-from-file is:

  • A response to handling a failed action step (link errors) creating the issue as an automated reaction/post-step. While additionally maintainers would be notified of the failure (I get emails) and the UI for the action showing a red X fail status symbol (action overview for scheduled jobs, or commit history if not on the PR check-status-suite).
  • Just another valid path/outcome for the link checking action/job. Thus no notification of job failure sent out, and the job is marked with a green tick as successful since it didn't actually fail when failed links were encountered.

Personally, if I'm having an issue opened for failed links, the job worked correctly, the job was not a failure (the step itself can be), and I'd rather the job didn't exit and notify me of such.

However for a PR, no issue is needed, and failed links is actionable as either a failed job (lint), or having another step take that information and do something with it on the PR (eg: adding/updating a comment, similar to this issue support). That decision can be handled with continue-on-error: true at the expense of not knowing of real failures?

- run: ${{ github.action_path }}/entrypoint.sh

- id: lychee
run: ${{ github.action_path }}/entrypoint.sh
env:
#https://github.com/actions/runner/issues/665

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to apply to the entire env block? The comment should be above env: line then, and perhaps reference the comment too? I assume it was this one.

- run: ${{ github.action_path }}/entrypoint.sh

- id: lychee
run: ${{ github.action_path }}/entrypoint.sh
env:
#https://github.com/actions/runner/issues/665
INPUT_GITHUB_TOKEN: ${{ inputs.GITHUB_TOKEN }}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of this ENV? You do not appear to use INPUT_GITHUB_TOKEN in your entrypoint.sh?

required: false
issueTitle:
description: "Title of Github issue which will be created if link check fails"
default: Link Checker Report

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be better to scope the issue with a prefix that indicates in the title it's a CI issue, and more specific hint of the content (since while it does contain a report, it's only being reported when failures are caught?):

Suggested change
default: Link Checker Report
default: 'ci(lint): Some monitored links are failing'

Comment on lines +37 to +43
Issue creation can optionally be disabled

```yaml
- name: Link Checker
uses: lycheeverse/[email protected]
with:
createIssue: false

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Issue creation can optionally be disabled
```yaml
- name: Link Checker
uses: lycheeverse/[email protected]
with:
createIssue: false
When failing links are found, `lychee-action` can create and update an issue with the `createIssue` input:
```yaml
- name: Link Checker
uses: lycheeverse/[email protected]
with:
createIssue: true

You might want to show off / mention other supported features too?

@polarathene
Copy link

I'd love to have the possibility to append a new comment to an existing issue. However this can be added
in a separate PR.

I'm still curious what the purpose for that would be, vs replacing the automated issue body.

It's easy enough to do regardless, I have a workflow for PRs that adds a comment to the PR with a link to a deployment preview of docs. Whenever the PR is updated, the new deployment preview link is updated in that comment (the action can alternatively delete the old comment and create a new one).


If possible I'd like to keep the number of dependencies to other Github actions at a minimum.
This is to avoid additional maintenance overhead when these dependencies change or get deprecated.

Wouldn't it be better to avoid the composite action entirely then? Or offer that separately from lychee-action (eg: lychee-action-reporter as a composited variant?)

  • Is all this worth maintaining vs a little more verbosity for a workflow job you'd rarely need to update (beyond the version bumps).
  • Will it risk burdening you with more maintenance/support queries vs just documenting an example of a common combination of actions like others do? (which is unofficial support, that you can more easily delegate to community to contribute/improve)

For now I'd like to merge the functionality in as is. Does it look good from your perspective @polarathene?
Would like to get an approval to be sure I didn't mess up.

Personally after providing that review for you, my opinion is this is not worth maintaining compared to having better documentation. Is there a strong demand for the composited action?

Provide an examples/ folder that shares common workflows, and optionally documents them well enough to grok with minimal experience. Users can help contribute to that, and the likelihood is probably more common than contributors to this nested composited approach.

We know of some common examples to cater for already:

  • PRs as a lint, fail when link errors are encountered. Optionally demonstrate using another action earlier to provide only inputs being changed in the PR (a complimentary markdown doc can detail when that isn't ideal, as well as why changed content instead of files can be less reliable too).
  • Scheduled jobs that report failures by creating or updating an existing open issue.
    • Also useful for broader link checking when rate-limit is a concern, as not only could the workflow cache be leveraged (in addition to lychee's own cache when that is fixed), but you're more likely to have a higher rate-limit budget vs PRs (no secrets such as GITHUB_TOKEN available for third-party contributor PRs, requires some workarounds to support, otherwise due to 60 requests/hour should exclude github service URLs).
  • API specific workarounds. I'm not sure about this one, but it's good to raise awareness. If someone wants to contribute their own workflow solutions for that, it could be helpful. One example might be for static sites, if deploying to GH Pages, rather than testing against the deployment, checkout the gh-pages branch and have lychee process the content there instead.

Also, we should release this as part of version 2.0 of the extension to avoid any breaking changes.
(Otherwise two issues would be created in the worst case — one by the existing call to create-issue-from-file and one by the now built-in issue creator.)

Sure, but I really don't think issue creation should be opt-out.

@polarathene
Copy link

Gotcha.

How do you plan for the issue number feature to be used? Currently it seems like:

  • Create a new issue each time the action is run and failures are found.
  • Or user creates an issue manually, or gets the issue number from the first automated issue creation and updates their workflow to use that.

Both of those seem awkward..? Whereas with last-issue-action, you don't have to worry about either of those.

Assuming lychee-action completes with an output of exit_code == 2 (failed links):

  • Create an issue when one doesn't already exist (or if one does but since closed)
  • Or update an issue that was already created for lychee-action (and still in an open state).
  • Close the open issue that was created for lychee-action when a PR or similar event closes the issue as resolved (automatic with Fixes or similar syntax in PRs upon merging them).
  • Next time lychee-action finds failures, a new issue is opened (the earlier steps repeat), and like before it will be updated automatically.
  • There is no manual/explicit changes required, nor any issue creation spam (in the sense of redundantly opening issues each time). That seems much nicer right?

If you did not visit the link I provided, this is what it'd look like (ignoring the composited action approach in this PR):

name: 'Manually trigger action (for testing)'
on: workflow_dispatch

jobs:
  lint-links-in-docs:
    name: 'Lint - Documentation Links (with issue reporting)'
    runs-on: ubuntu-22.04
    permissions:
      contents: read
      issues: write
    steps:
      # Permissions (contents: read)
      - uses: actions/checkout@v3

      - name: 'Check links in docs'
        id: lychee
        uses: lycheeverse/[email protected]
        continue-on-error: true
        with:
          args: --verbose --no-progress -- docs/**/*
          output: ${{ runner.temp }}/lychee-report.md

      # Below manages issue creation/updating when failing links are found:

      # Permissions (issues: read)
      - name: 'Check for an existing lychee-action issue'
        id: last-issue
        uses: micalevisk/[email protected]
        # NOTE: This env won't be necessary soon:
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        # Find the last updated open issue with a `ci-lint-links` label:
        with:
          state: open
          labels: ci-lint-links

      # Permissions (issues: write)
      - name: 'Create a new issue, or update an existing one'
        if: ${{ steps.lychee.outputs.exit_code == 2 }}
        uses: peter-evans/create-issue-from-file@v4
        with:
          title: 'ci(lint): Docs have failing links'
          content-filepath: ${{ runner.temp }}/lychee-report.md
          # If issue_number is empty (no match found), create a new issue, otherwise update this matched issue:
          issue-number: ${{ steps.last-issue.outputs.issue_number }}
          # Add a label unique enough to search for, and any other labels relevant to maintainers:
          labels: ci-lint-links, docs, bug

Well.. that would work, except lychee-action doesn't have any outputs available to other steps because it's only available to the other steps in it's current composite action form that I see is already in use prior to this PR 😅

To verify, just swap out those last two steps of the example to view the available outputs. It will show that it's empty even when output exit_code == 2. Which means the if condition I have in the example will never be true until that problem is resolved.

      - name: 'List lychee outputs'
        run: |
          echo '::echo::on'
          echo -e "lychee.outputs:\n${{ toJSON(steps.lychee.outputs) }}"

@mre
Copy link
Member Author

mre commented Jul 4, 2022

Thanks a lot for the excellent review. I will go through the comments once I find some time but from a cursory look all suggestions make sense. You are right in that coupling issue creation with this action is probably not the way to go. I've changed my mind. Instead, let's work on the examples folder as you suggested.

@polarathene
Copy link

You are right in that coupling issue creation with this action is probably not the way to go. I've changed my mind.

👍

Instead, let's work on the examples folder as you suggested.

I can contribute these, and refactor entrypoint.sh (or the action itself due to the exit_code output not being available to other steps).

In exchange, could you please redirect your time on resolving the lychee --cache bug?

@mre
Copy link
Member Author

mre commented Jul 4, 2022

Please do, that would be awesome!

In exchange, could you please redirect your time on resolving the lychee --cache bug?

Sounds good.

@mre
Copy link
Member Author

mre commented Jul 27, 2022

I can contribute these, and refactor entrypoint.sh (or the action itself due to the exit_code output not being available to other steps).

@polarathene do you still plan to work on the example folder? The exit code should be propagated correctly now.
In any case, I guess we can close this?

@polarathene
Copy link

@polarathene do you still plan to work on the example folder?

Yes, sorry been rather busy lately 😅

The exit code should be propagated correctly now.
In any case, I guess we can close this?

👍

@mre mre closed this Aug 11, 2022
@tooomm
Copy link
Contributor

tooomm commented Aug 22, 2022

I got lost in the conversation here.
Are there some examples in place that explain how to setup the action to update already existing issues?

@polarathene
Copy link

Are there some examples in place that explain

Any particular examples you're after?

I'm unfortunately swamped right now, contributing examples is still on my todo list but I have deadlines to meet 😅

@tooomm
Copy link
Contributor

tooomm commented Sep 5, 2022

Any particular examples you're after?

I want to automatically create an issue once errors are found with lychee-action.
The issue should be updated once new information is available (add new errors, or remove fixed ones).
The issue should be closed once all errors are resolved.

My first impression was that it should work already, one just needs to know the correct configuration which there are no examples of yet. Hence my question.
But it looks like this does currently not work as lychee-action is not providing any outputs to other steps for now?
Maybe this is better off in an issue as long as it's not working?

I'm unfortunately swamped right now, contributing examples is still on my todo list but I have deadlines to meet 😅

Great to hear that you still plan on working on it! 👍

@polarathene
Copy link

polarathene commented Sep 5, 2022

Maybe this is better off in an issue as long as it's not working?

Open an issue and mention me in it, it can track the request for that example.

My first impression was that it should work already, one just needs to know the correct configuration which there are no examples of yet.

I believe I had something similar to what you're asking for when I was working on a similar workflow. I didn't manage to complete it as it relied on some other actions to update, that should be taken care of now.

I hope you don't mind the delay, but I should be able to find time to sort that out for you this month. If I can get on top of things this week, it might be possible to have a workflow example available this weekend 👍

We decided that lychee-action should be focused on what it does best, and delegate other parts to actions that do those things well, so you'll have a workflow that uses a few different actions together to achieve this.


This is a copy/paste from a workflow I shared elsewhere which should be able to be revised to meet your requirements.

This was while working on a PR for last-issue to get some changes for the 2.0 release that I requested, it may need some other changes. link-reporter would be lychee-action but was stubbed out to test the exit code behaviour on the other two actions for issue management, which you would use to achieve your goal.

If I remember correctly, this would create an issue when link-reporter outputs the markdown file with exit code of 2 (failing links), last-issue action prior to that would provide an existing open issue to update instead if available.

So this just needs to consider a successful run of lychee-action to close any issue that last-issue might report as open. Then the next time, a new issue is created and it repeats (old closed issue is not re-cycled, which I think is the right approach if any discussion is involved).

name: 'Testing - Manually trigger action'
on:
  workflow_dispatch:
    inputs:
      exit-code:
        type: number
        description: Override the EXIT_CODE
      kebab-bool:
        type: boolean
        description: Test kebab-case conditions
        default: true

jobs:
  lint-links-in-docs:
    name: 'Lint - Documentation Links (with issue reporting)'
    runs-on: ubuntu-22.04
    permissions:
      contents: read
      issues: write
    steps:
      - uses: actions/checkout@v3

      - id: link-reporter
        run: |
          echo '**report content here**' > "${{ runner.temp }}/report.md"

          # Only set when an explicit value is given to workflow input,
          EXIT_CODE=${{ github.event.inputs.exit-code }}
          # Otherwise fallback to 0:
          [[ -z ${EXIT_CODE} ]] && EXIT_CODE=0

          # Disabling this bool will set `EXIT_CODE=2`
          [[ ${{ github.event.inputs.kebab-bool }} == 'false' ]] && EXIT_CODE=2

          echo '::echo::on'
          echo "EXIT_CODE: ${EXIT_CODE}"

          # Test kebab-case output condition:
          echo "::set-output name=exit-code::${EXIT_CODE}"

      # Below manages issue creation/updating when failing links are found:

      - name: 'Check for an existing link-reporter issue'
        id: last-issue
        uses: micalevisk/[email protected]
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          state: open
          labels: ci-lint-links

      - name: 'Create a new issue, or update an existing one'
        if: ${{ steps.link-reporter.outputs.exit-code == 2 }}
        uses: peter-evans/create-issue-from-file@v4
        with:
          title: 'ci(lint): Docs have failing links'
          content-filepath: ${{ runner.temp }}/report.md
          issue-number: ${{ steps.last-issue.outputs.issue_number }}
          labels: ci-lint-links, bug

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants