Skip to content

Commit

Permalink
feat: accept containers to execute actions (#180)
Browse files Browse the repository at this point in the history
* refactor: remove no-op `workflows` from module

* refactor: use base container for config

* feat: accept containers to execute actions

* docs: update README.md

* refactor: update actions/runtime with new gale DX

* docs: add changie notes
  • Loading branch information
aweris authored Nov 8, 2023
1 parent bb70a2f commit e0f087c
Show file tree
Hide file tree
Showing 13 changed files with 266 additions and 189 deletions.
6 changes: 6 additions & 0 deletions .changes/unreleased/Added-20231108-121519.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Added
body: Introduced a new `--container` option to specify the container type for runners.
time: 2023-11-08T12:15:19.019065+01:00
custom:
Author: aweris
PR: "180"
6 changes: 6 additions & 0 deletions .changes/unreleased/Breaking-20231108-120544.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: Breaking
body: Removed the `workflows` subcommand from the module. `list` and `run` commands are now available directly under module root.
time: 2023-11-08T12:05:44.825203+01:00
custom:
Author: aweris
PR: "180"
7 changes: 7 additions & 0 deletions .changes/unreleased/Changed-20231108-121439.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: Changed
body: Renamed the command line option `--runner-image` to `--image`. This change affects
all commands where `--runner-image` was previously used.
time: 2023-11-08T12:14:39.28384+01:00
custom:
Author: aweris
PR: "180"
87 changes: 44 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,66 +48,67 @@ To get a list of workflows, you can use the dagger call workflows list command.
Below is the help output showing the usage and options:

```shell
Usage:
dagger call workflows list [flags]

Aliases:
list, List

Flags:
--branch string Git branch to checkout. Used with --repo. If tag and branch are both specified, tag takes precedence.
-h, --help help for list
--repo string Name of the repository. Format: owner/name.
--source Directory Directory containing the repository source. Has precedence over repo.
--tag string Git tag to checkout. Used with --repo. If tag and branch are both specified, tag takes precedence.
--workflows-dir string Path to the workflow directory. (default ".github/workflows")
List returns a list of workflows and their jobs with the given options.

Usage:
dagger call list [flags]

Flags:
--branch string Branch name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch.
-h, --help help for list
--repo string The name of the repository. Format: owner/name.
--source Directory The directory containing the repository source. If source is provided, rest of the options are ignored.
--tag string Tag name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch.
--workflows-dir string Path to the workflows' directory. (default: .github/workflows)
```
#### Examples
List all workflows for current repository:
```shell
dagger call workflows list --source "."
dagger call list --source "."
```
List workflows for a specific repository and directory:
```shell
dagger call workflows list --repo aweris/gale --branch main --workflows-dir examples/workflows
dagger call list --repo aweris/gale --branch main --workflows-dir examples/workflows
```
### Run a Workflow
For running workflows, you'll mainly use `dagger [call|download] workflows run [flags] [sub-command]`. Below is
For running workflows, you'll mainly use `dagger [call|download] run [flags] [sub-command]`. Below is
the help output showing the usage and options:

```shell
Usage:
dagger call workflows run [flags]
dagger call workflows run [command]

Aliases:
run, Run

Available Commands:
config Configuration for the workflow run.
directory Directory returns the directory of the workflow run information.
sync Sync evaluates the workflow run and returns the container at executed the workflow.

Flags:
--branch string Git branch to checkout. Used with --repo. If tag and branch are both specified, tag takes precedence.
--event string Name of the event that triggered the workflow. (default "push")
--event-file File The file with the complete webhook json event payload.
-h, --help help for run
--job string Name of the job to run. If empty, all jobs will be run.
--repo string Name of the repository. Format: owner/name.
--runner-debug Enables debug mode.
--runner-image string Docker image to use for the runner. (default "ghcr.io/dagger/gale:latest")
--source Directory Directory containing the repository source. Has precedence over repo.
--tag string Git tag to checkout. Used with --repo. If tag and branch are both specified, tag takes precedence.
--token Secret GitHub token to use for authentication.
--workflow string Name of the workflow to run.
Run runs the workflow with the given options.
Usage:
dagger call run [flags]
dagger call run [command]
Available Commands:
config Configuration for the workflow run.
directory Directory returns the directory of the workflow run information.
sync Sync runs the workflow and returns the container that ran the workflow.
Flags:
--branch string Branch name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch.
--container Container Container to use for the runner. If --image and --container provided together, --image takes precedence.
--event string Name of the event that triggered the workflow. e.g. push
--event-file File File with the complete webhook event payload.
-h, --help help for run
--image string Image to use for the runner. If --image and --container provided together, --image takes precedence.
--job string Name of the job to run. If empty, all jobs will be run.
--repo string The name of the repository. Format: owner/name.
--runner-debug Enables debug mode.
--source Directory The directory containing the repository source. If source is provided, rest of the options are ignored.
--tag string Tag name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch.
--token Secret GitHub token to use for authentication.
--workflow string Name of the workflow to run.
--workflow-file File External workflow file to run.
--workflows-dir string Path to the workflows directory. (default: .github/workflows)
```

#### Sub-Commands
Expand All @@ -123,7 +124,7 @@ dagger call workflow run ... --workflow build sync
The help output for directory option
```shell
Usage:
dagger download workflows run directory [flags]
dagger download run directory [flags]
Aliases:
directory, Directory
Expand All @@ -146,7 +147,7 @@ dagger download workflow run ... --workflow build directory --export-path .gale/
Running a workflow for remote repository and downloading exporting the workflow run data and artifacts:

```shell
dagger download --focus=false workflows run --repo kubernetes/minikube --branch master --workflow build --job build_minikube --token $GITHUB_TOKEN directory --export-path .gale/exports --include-artifacts
dagger download --focus=false run --repo kubernetes/minikube --branch master --workflow build --job build_minikube --token $GITHUB_TOKEN directory --export-path .gale/exports --include-artifacts
```

**Notes for Above Example:**
Expand Down
17 changes: 11 additions & 6 deletions daggerverse/actions/runtime/action_run.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package main

import (
"actions-runtime/model"
"fmt"

"actions-runtime/model"
)

type ActionRun struct {
Expand Down Expand Up @@ -38,8 +39,11 @@ type ActionRunConfig struct {
// File with the complete webhook event payload.
EventFile *File

// Image to use for the runner.
RunnerImage string
// Image to use for the runner. If --image and --container provided together, --image takes precedence.
Image string

// Container to use for the runner. If --image and --container provided together, --image takes precedence.
Container *Container

// Enables debug mode.
RunnerDebug bool
Expand All @@ -64,20 +68,21 @@ func (ar *ActionRun) Sync() (*Container, error) {
return nil, err
}

opts := GaleWorkflowsRunOpts{
opts := GaleRunOpts{
Source: ar.Config.Source,
Repo: ar.Config.Repo,
Tag: ar.Config.Tag,
Branch: ar.Config.Branch,
WorkflowFile: wf,
Event: ar.Config.Event,
EventFile: ar.Config.EventFile,
RunnerImage: ar.Config.RunnerImage,
Image: ar.Config.Image,
Container: ar.Config.Container,
RunnerDebug: ar.Config.RunnerDebug,
Token: ar.Config.Token,
}

return dag.Gale().Workflows().Run(opts).Sync(), nil
return dag.Gale().Run(opts).Sync(), nil
}

// getWorkflowFile returns a workflow file with the given uses, env, and with.
Expand Down
9 changes: 6 additions & 3 deletions daggerverse/actions/runtime/actions_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ func (m *ActionsRuntime) Run(
event Optional[string],
// File with the complete webhook event payload.
eventFile Optional[*File],
// Image to use for the runner.
runnerImage Optional[string],
// Image to use for the runner. If --image and --container provided together, --image takes precedence.
image Optional[string],
// Container to use for the runner. If --image and --container provided together, --image takes precedence.
container Optional[*Container],
// Enables debug mode.
runnerDebug Optional[bool],
// GitHub token to use for authentication.
Expand All @@ -36,7 +38,8 @@ func (m *ActionsRuntime) Run(
With: []string{},
Event: event.GetOr("push"),
EventFile: eventFile.GetOr(nil),
RunnerImage: runnerImage.GetOr("ghcr.io/catthehacker/ubuntu:act-latest"),
Image: image.GetOr(""), // default value handled by gale module. Handling it here would override the container if it is provided.
Container: container.GetOr(nil),
RunnerDebug: runnerDebug.GetOr(false),
Token: token.GetOr(nil),
},
Expand Down
2 changes: 1 addition & 1 deletion daggerverse/actions/runtime/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ require (
github.com/stretchr/testify v1.8.3 // indirect
github.com/vektah/gqlparser/v2 v2.5.6 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/sync v0.3.0
golang.org/x/sync v0.4.0
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)
4 changes: 2 additions & 2 deletions daggerverse/actions/runtime/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ github.com/vektah/gqlparser/v2 v2.5.6 h1:Ou14T0N1s191eRMZ1gARVqohcbe1e8FrcONScsq
github.com/vektah/gqlparser/v2 v2.5.6/go.mod h1:z8xXUff237NntSuH8mLFijZ+1tjV1swDbpDqjJmk6ME=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
Expand Down
124 changes: 122 additions & 2 deletions daggerverse/gale/gale.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,128 @@
package main

import (
"context"
"fmt"
"strings"
)

// Gale is a Dagger module for running Github Actions workflows.
type Gale struct{}

func (g *Gale) Workflows() *Workflows {
return new(Workflows)
// List returns a list of workflows and their jobs with the given options.
func (g *Gale) List(
// context to use for the operation
ctx context.Context,
// The directory containing the repository source. If source is provided, rest of the options are ignored.
source Optional[*Directory],
// The name of the repository. Format: owner/name.
repo Optional[string],
// Tag name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch.
tag Optional[string],
// Branch name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch.
branch Optional[string],
// Path to the workflows' directory. (default: .github/workflows)
workflowsDir Optional[string],
) (string, error) {
workflows := getWorkflowsDir(source, repo, tag, branch, workflowsDir)

sb := strings.Builder{}

err := walkWorkflowDir(ctx, workflowsDir, workflows,
func(ctx context.Context, path string, file *File) error {
// dagger do not support maps yet, so we're defining anonymous struct to unmarshal the yaml file to avoid
// hit this limitation.
var workflow struct {
Name string `yaml:"name"`
Jobs map[string]interface{} `yaml:"jobs"`
}

if err := unmarshalContentsToYAML(ctx, file, &workflow); err != nil {
return err
}

sb.WriteString("Workflow: ")
if workflow.Name != "" {
sb.WriteString(fmt.Sprintf("%s (path: %s)\n", workflow.Name, path))
} else {
sb.WriteString(fmt.Sprintf("%s\n", path))
}

sb.WriteString("Jobs:\n")

for job := range workflow.Jobs {
sb.WriteString(fmt.Sprintf(" - %s\n", job))
}

sb.WriteString("\n") // extra empty line

return nil
},
)

if err != nil {
return "", err
}

return sb.String(), nil
}

// Run runs the workflow with the given options.
func (g *Gale) Run(
// The directory containing the repository source. If source is provided, rest of the options are ignored.
source Optional[*Directory],
// The name of the repository. Format: owner/name.
repo Optional[string],
// Tag name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch.
tag Optional[string],
// Branch name to check out. Only one of branch or tag can be used. Precedence is as follows: tag, branch.
branch Optional[string],
// Path to the workflows directory. (default: .github/workflows)
workflowsDir Optional[string],
// External workflow file to run.
workflowFile Optional[*File],
// Name of the workflow to run.
workflow Optional[string],
// Name of the job to run. If empty, all jobs will be run.
job Optional[string],
// Name of the event that triggered the workflow. e.g. push
event Optional[string],
// File with the complete webhook event payload.
eventFile Optional[*File],
// Image to use for the runner. If --image and --container provided together, --image takes precedence.
image Optional[string],
// Container to use for the runner. If --image and --container provided together, --image takes precedence.
container Optional[*Container],
// Enables debug mode.
runnerDebug Optional[bool],
// GitHub token to use for authentication.
token Optional[*Secret],
) *WorkflowRun {
var base *Container

if image, ok := image.Get(); ok {
base = dag.Container().From(image)
} else if container, ok := container.Get(); ok {
base = container
} else {
base = dag.Container().From("ghcr.io/catthehacker/ubuntu:act-latest")
}

return &WorkflowRun{
Config: WorkflowRunConfig{
Base: base,
Source: source.GetOr(nil),
Repo: repo.GetOr(""),
Branch: branch.GetOr(""),
Tag: tag.GetOr(""),
WorkflowsDir: workflowsDir.GetOr(".github/workflows"),
WorkflowFile: workflowFile.GetOr(nil),
Workflow: workflow.GetOr(""),
Job: job.GetOr(""),
Event: event.GetOr("push"),
EventFile: eventFile.GetOr(nil),
RunnerDebug: runnerDebug.GetOr(false),
Token: token.GetOr(nil),
},
}
}
1 change: 1 addition & 0 deletions daggerverse/gale/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"

"gopkg.in/yaml.v3"
)

Expand Down
Loading

0 comments on commit e0f087c

Please sign in to comment.