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

Initial implementation of the frizbee action #2

Merged
merged 3 commits into from
Jun 11, 2024

Conversation

rdimitrov
Copy link
Member

@rdimitrov rdimitrov commented Jun 10, 2024

Initial implementation of the Frizbee Action.

Details:

  • Supports GitHub Actions, Dockerfiles and all yaml/yml files containing known container image references, i.e. docker-compose files, Kubernetes files, etc.
  • Supports opening PRs suggesting repository owners to pin their actions or container images

Todo:

  • The default GITHUB_TOKEN granted from the action run does not have the workflows permissions which limits the action to open PRs against the workflow files. To resolve this, the user would have to create a new token with the correct permissions and assign it to the action.
  • Support re-running the action if there's previous PR created
  • Test it from another repo when it's published - stacklok/frizbee-action@v0.0.1
  • There's a test.yml workflow and a tests folder with a bunch of example files. Let me know if you want these deleted now or we can keep them until we are okay with the functionality of the initial version.
  • Add support for checking the content of the PR instead of the whole repository

Fixes: stacklok/frizbee#149

@rdimitrov rdimitrov force-pushed the implement-frizbee-action branch 3 times, most recently from 1eb5a37 to 6e737d6 Compare June 11, 2024 08:42
Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
@rdimitrov rdimitrov force-pushed the implement-frizbee-action branch 6 times, most recently from 76f5bef to 16688a0 Compare June 11, 2024 11:24
@rdimitrov rdimitrov marked this pull request as ready for review June 11, 2024 11:24
@rdimitrov rdimitrov changed the title [Draft] Initial implementation of the frizbee action Initial implementation of the frizbee action Jun 11, 2024
@rdimitrov rdimitrov force-pushed the implement-frizbee-action branch 8 times, most recently from 11d6634 to ce0a2d7 Compare June 11, 2024 11:52
@@ -5,10 +5,30 @@ branding:
icon: "at-sign"
color: "green"
inputs:
GITHUB_TOKEN:
Copy link
Member Author

Choose a reason for hiding this comment

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

This is already there from the GITHUB environment

Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
@rdimitrov rdimitrov force-pushed the implement-frizbee-action branch from ce0a2d7 to 5898d4f Compare June 11, 2024 12:23
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this checked in accidently? We should not need minder

Copy link
Member Author

Choose a reason for hiding this comment

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

The tests.yml workflow and everything under the tests directory are test files to test the action with. My thought was to leave them there until we make this ready and remove them afterwards. I should have mentioned this explicitly.

}

// cloneRepository clones the repository and returns a billy.Filesystem interface to interact with it
func cloneRepository(url, owner, accessToken string) (billy.Filesystem, *git.Repository, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if there is an alternative approach to cloning? This might take a long time if there are large blobs in the repo.

I guess a lot of this is based on the approach, is this intercepting PR's or a workflow that is scheduled?

Copy link
Member Author

Choose a reason for hiding this comment

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

The use case for this is when the actions runs from a scheduled run. We can do something else once we add support for checking the contents of a PR patch too.

Copy link
Contributor

Choose a reason for hiding this comment

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

Intercepting the PRs would have the added benefit of not requiring as high privileges I think.

About cloning, I view it as acceptable for because the action is not typically run on infra we pay for :-) we can then optimize the clone with something like git sparse checkout since the action configuration already tells us which files or directories to look at.

description: "Docker Compose files to correct"
required: false
default: ""
open_pr:
Copy link
Contributor

Choose a reason for hiding this comment

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

what would happen if open_pr is false, I guess it would never work?

Copy link
Member Author

Choose a reason for hiding this comment

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

If open_pr is false it would run the action, parse the files, and output what it did, perhaps fail the run if fail_on_unpinned is set, but it won't create a PR.

Signed-off-by: Radoslav Dimitrov <radoslav@stacklok.com>
@rdimitrov rdimitrov force-pushed the implement-frizbee-action branch from cf31c95 to 5602ab2 Compare June 11, 2024 12:58
@rdimitrov
Copy link
Member Author

rdimitrov commented Jun 11, 2024

The Trivy scan failure is because of an indirect dependency.

@rdimitrov
Copy link
Member Author

Example PR:

Example test runs with different configurations -

@jhrozek
Copy link
Contributor

jhrozek commented Jun 11, 2024

The Trivy scan failure is because of an indirect dependency.

if the dep can't be updated, then we need to add a trivy ignore (let me know if you want me to do that)

@@ -1,5 +1,4 @@
FROM golang:alpine3.19@sha256:0466223b8544fb7d4ff04748acc4d75a608234bf4e79563bff208d2060c0dd79
Copy link
Contributor

Choose a reason for hiding this comment

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

do you know if dependabot automatically bumps these? I think it's easier to use the golang:goversion images to see what go version are we using (I don't particulary care about the OS version, we're not installing anything anyway)

dockerfiles:
description: "Dockerfiles to correct"
required: false
default: "Dockerfile"
Copy link
Contributor

Choose a reason for hiding this comment

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

as discussed on meet, I think a list of files or dirs would be more useful, e.g. in minder we have:

./docker/reminder/Dockerfile
./docker/minder/Dockerfile

but the default is sensible, great!


The default `GITHUB_TOKEN` doesn't have the necessary permissions (`workflows`) to open a PR.
In case you want to use the `open_pr` feature, you will need to create a new token with the correct scope, add it as a secret
and pass it to the action through the `GITHUB_TOKEN` environment variable.
Copy link
Contributor

Choose a reason for hiding this comment

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

do we have a way to tell the user in a nice way (some introspection of the token, e.g. hitting the /user endpoint with it)

import (
"context"
"errors"
"fmt"
Copy link
Contributor

Choose a reason for hiding this comment

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

for later: we should lint the code before it gets too big

func main() {
// This is a placeholder for the main function
ctx := context.Background()
Copy link
Contributor

Choose a reason for hiding this comment

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

do you think it makes sense to provide a sensible timeout here (a couple of minutes maybe?) to avoid running the action for too long? Or is it better set somewhere in the action config?

// initAction initializes the frizbee action - reads the environment variables, creates the GitHub client, etc.
func initAction(ctx context.Context) (*action.FrizbeeAction, error) {
// Get the GitHub token from the environment
token := os.Getenv("GITHUB_TOKEN")
Copy link
Contributor

Choose a reason for hiding this comment

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

would it make testing the function later easier to pass the tokens etc as parameters?

}

// Clone the repository
fs, repo, err := cloneRepository(fmt.Sprintf("https://github.com/%s", repoFullName), repoOwner, token)
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure if there's any use-case, but we might want to use the GH API to get the clone URL rather than constructing it ourselves.

log.Fatalf("failed to close file %s: %v", path, err) // nolint:errcheck
}
}()
_, err = fmt.Fprintf(f, "%s", content)
Copy link
Contributor

Choose a reason for hiding this comment

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

why not io.WriteString and skip the formatting parameter?

// Commit the change
_, err = worktree.Commit(fmt.Sprintf("Update %s by pinning its image references", path), &git.CommitOptions{
Author: &object.Signature{
Name: "github-actions[bot]",
Copy link
Contributor

Choose a reason for hiding this comment

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

should we use a specific author name?

// createPR creates a new pull request with the changes made so far
func (fa *FrizbeeAction) createPR(ctx context.Context) error {
// Create a new branch for the PR
branchName := "frizbee-action-patch"
Copy link
Contributor

Choose a reason for hiding this comment

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

const?

for _, pr := range openPrs {
if pr.GetHead().GetRef() == branchName {
fmt.Printf("PR %d already exists\n", pr.GetNumber())
return nil
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't we update a PR if it exists?

Copy link
Contributor

@jhrozek jhrozek left a comment

Choose a reason for hiding this comment

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

I left a couple of comments inline, but I say let's merge this, get the codebase rolling and then iterate (we can either go back to the comments here and just reply to them or create issues)

@lukehinds
Copy link
Contributor

I am happy if you folks think its is in decent shape. I have a feeling I prefer a scheduled run dependabot style type experience as default, but happy to discuss more if need be.

@rdimitrov
Copy link
Member Author

Let's merge this so we can get it rolling and I'll file separate issues for the comments @lukehinds and @jhrozek made so we keep and address their feedback 👍 Thank you both!

@rdimitrov rdimitrov merged commit 327fadc into stacklok:main Jun 11, 2024
1 of 2 checks passed
@rdimitrov rdimitrov deleted the implement-frizbee-action branch June 11, 2024 21:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Frizbee Action
3 participants