Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions blueprint.cue
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ global: {
]
}
deployment: {
foundry: api: "https://foundry.projectcatalyst.io"
registries: {
containers: "ghcr.io/input-output-hk/catalyst-forge"
modules: ci.providers.aws.ecr.registry + "/catalyst-deployments"
Expand All @@ -87,5 +88,6 @@ global: {
repo: {
defaultBranch: "master"
name: "input-output-hk/catalyst-forge"
url: "https://github.com/input-output-hk/catalyst-forge"
}
}
1 change: 1 addition & 0 deletions cli/Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
ENV GOMODCACHE=/go/modcache
CACHE --persist --sharing shared /go

COPY ../foundry/api+src/src /foundry/api
COPY ../lib/project+src/src /lib/project
COPY ../lib/schema+src/src /lib/schema
COPY ../lib/tools+src/src /lib/tools
Expand Down Expand Up @@ -49,7 +50,7 @@
test:
FROM +build

RUN go test ./...

Check failure on line 53 in cli/Earthfile

View workflow job for this annotation

GitHub Actions / ci / test / ./cli+test

Error

The command RUN go test ./... did not complete successfully. Exit code 1

github:
FROM scratch
Expand Down
6 changes: 6 additions & 0 deletions cli/cmd/cmds/deploy/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package deploy

type DeployCmd struct {
Create DeployCreateCmd `cmd:"create" help:"Create a new deployment."`
Get DeployGetCmd `cmd:"get" help:"Get a deployment."`
}
35 changes: 35 additions & 0 deletions cli/cmd/cmds/deploy/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package deploy

import (
"context"
"fmt"
"time"

"github.com/input-output-hk/catalyst-forge/cli/pkg/run"
"github.com/input-output-hk/catalyst-forge/cli/pkg/utils"
api "github.com/input-output-hk/catalyst-forge/foundry/api/client"
)

type DeployCreateCmd struct {
ReleaseID string `arg:"" help:"The release ID to deploy."`
Url string `short:"u" help:"The URL to the Foundry API server (overrides global config)."`
}

func (c *DeployCreateCmd) Run(ctx run.RunContext) error {
url, err := utils.GetFoundryURL(ctx, c.Url)
if err != nil {
return err
}

client := api.NewClient(url, api.WithTimeout(10*time.Second))
deployment, err := client.CreateDeployment(context.Background(), c.ReleaseID)
if err != nil {
return fmt.Errorf("could not create deployment: %w", err)
}

if err := utils.PrintJson(deployment, true); err != nil {
return err
}

return nil
}
36 changes: 36 additions & 0 deletions cli/cmd/cmds/deploy/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package deploy

import (
"context"
"fmt"
"time"

"github.com/input-output-hk/catalyst-forge/cli/pkg/run"
"github.com/input-output-hk/catalyst-forge/cli/pkg/utils"
api "github.com/input-output-hk/catalyst-forge/foundry/api/client"
)

type DeployGetCmd struct {
ReleaseID string `arg:"" help:"The release ID."`
DeployID string `arg:"" help:"The deployment ID."`
Url string `short:"u" help:"The URL to the Foundry API server (overrides global config)."`
}

func (c *DeployGetCmd) Run(ctx run.RunContext) error {
url, err := utils.GetFoundryURL(ctx, c.Url)
if err != nil {
return err
}

client := api.NewClient(url, api.WithTimeout(10*time.Second))
deployment, err := client.GetDeployment(context.Background(), c.ReleaseID, c.DeployID)
if err != nil {
return fmt.Errorf("could not show deployment: %w", err)
}

if err := utils.PrintJson(deployment, true); err != nil {
return err
}

return nil
}
7 changes: 7 additions & 0 deletions cli/cmd/cmds/release/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package release

type ReleaseCmd struct {
Create ReleaseCreateCmd `cmd:"create" help:"Create a new release for a project."`
List ReleaseListCmd `cmd:"list" help:"List all releases for a project."`
Get ReleaseGetCmd `cmd:"get" help:"Get a release."`
}
111 changes: 111 additions & 0 deletions cli/cmd/cmds/release/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package release

import (
"context"
"errors"
"fmt"
"log/slog"
"time"

"github.com/input-output-hk/catalyst-forge/cli/pkg/run"
"github.com/input-output-hk/catalyst-forge/cli/pkg/utils"
api "github.com/input-output-hk/catalyst-forge/foundry/api/client"
"github.com/input-output-hk/catalyst-forge/lib/project/project"
"github.com/input-output-hk/catalyst-forge/lib/tools/fs"
"github.com/input-output-hk/catalyst-forge/lib/tools/git/github"
)

type ReleaseCreateCmd struct {
Deploy bool `short:"d" help:"Automatically create a new deployment for the release."`
Project string `arg:"" help:"The path to the project to create a new release for." kong:"arg,predictor=path"`
Url string `short:"u" help:"The URL to the Foundry API server (overrides global config)."`
}

func (c *ReleaseCreateCmd) Run(ctx run.RunContext) error {
exists, err := fs.Exists(c.Project)
if err != nil {
return fmt.Errorf("could not check if project exists: %w", err)
} else if !exists {
return fmt.Errorf("project does not exist: %s", c.Project)
}

project, err := ctx.ProjectLoader.Load(c.Project)
if err != nil {
return fmt.Errorf("could not load project: %w", err)
}

commit, err := getCommitHash(project, ctx.Logger)
if err != nil {
return fmt.Errorf("could not get commit hash: %w", err)
}

branch, err := getBranch(project, ctx.Logger)
if err != nil {
return fmt.Errorf("could not get branch: %w", err)
}

// Only set the branch if it is not the default branch
if branch == project.Blueprint.Global.Repo.DefaultBranch {
branch = ""
}

path, err := project.GetRelativePath()
if err != nil {
return fmt.Errorf("could not get project path: %w", err)
}

var url string
if c.Url == "" {
if project.Blueprint.Global == nil ||
project.Blueprint.Global.Deployment == nil ||
project.Blueprint.Global.Deployment.Foundry.Api == "" {
return errors.New("no foundry URL provided and no URL found in the root blueprint")
}

url = project.Blueprint.Global.Deployment.Foundry.Api
} else {
url = c.Url
}

client := api.NewClient(url, api.WithTimeout(10*time.Second))
release, err := client.CreateRelease(context.Background(), &api.Release{
SourceRepo: project.Blueprint.Global.Repo.Url,
SourceCommit: commit,
SourceBranch: branch,
Project: project.Name,
ProjectPath: path,
Bundle: "something",
}, c.Deploy)
if err != nil {
return fmt.Errorf("could not create release: %w", err)
}

if err := utils.PrintJson(release, true); err != nil {
return err
}

return nil
}

func getCommitHash(project project.Project, logger *slog.Logger) (string, error) {
if github.InGithubActions() {
ghr := github.NewDefaultGithubRepo(logger)
return ghr.GetCommit()
}

obj, err := project.Repo.HeadCommit()
if err != nil {
return "", err
}

return obj.Hash.String(), nil
}

func getBranch(project project.Project, logger *slog.Logger) (string, error) {
if github.InGithubActions() {
ghr := github.NewDefaultGithubRepo(logger)
return ghr.GetBranch(), nil
}

return project.Repo.GetCurrentBranch()
}
35 changes: 35 additions & 0 deletions cli/cmd/cmds/release/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package release

import (
"context"
"fmt"
"time"

"github.com/input-output-hk/catalyst-forge/cli/pkg/run"
"github.com/input-output-hk/catalyst-forge/cli/pkg/utils"
api "github.com/input-output-hk/catalyst-forge/foundry/api/client"
)

type ReleaseGetCmd struct {
ReleaseID string `arg:"" help:"The ID of the release."`
Url string `short:"u" help:"The URL to the Foundry API server (overrides global config)."`
}

func (c *ReleaseGetCmd) Run(ctx run.RunContext) error {
url, err := utils.GetFoundryURL(ctx, c.Url)
if err != nil {
return err
}

client := api.NewClient(url, api.WithTimeout(10*time.Second))
release, err := client.GetRelease(context.Background(), c.ReleaseID)
if err != nil {
return fmt.Errorf("could not show release: %w", err)
}

if err := utils.PrintJson(release, true); err != nil {
return err
}

return nil
}
35 changes: 35 additions & 0 deletions cli/cmd/cmds/release/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package release

import (
"context"
"fmt"
"time"

"github.com/input-output-hk/catalyst-forge/cli/pkg/run"
"github.com/input-output-hk/catalyst-forge/cli/pkg/utils"
api "github.com/input-output-hk/catalyst-forge/foundry/api/client"
)

type ReleaseListCmd struct {
Project string `arg:"" help:"The project to list releases for."`
Url string `short:"u" help:"The URL to the Foundry API server (overrides global config)."`
}

func (c *ReleaseListCmd) Run(ctx run.RunContext) error {
url, err := utils.GetFoundryURL(ctx, c.Url)
if err != nil {
return err
}

client := api.NewClient(url, api.WithTimeout(10*time.Second))
releases, err := client.ListReleases(context.Background(), c.Project)
if err != nil {
return fmt.Errorf("could not list releases: %w", err)
}

if err := utils.PrintJson(releases, true); err != nil {
return err
}

return nil
}
2 changes: 1 addition & 1 deletion cli/cmd/cmds/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (c *ScanCmd) Run(ctx run.RunContext) error {
return fmt.Errorf("root path does not exist: %s", rootPath)
}

projects, err := scan.ScanProjects(rootPath, ctx.ProjectLoader, &ctx.FSWalker, ctx.Logger)
projects, err := scan.ScanProjects(rootPath, ctx.ProjectLoader, ctx.Walker, ctx.Logger)
if err != nil {
return err
}
Expand Down
34 changes: 22 additions & 12 deletions cli/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import (
"github.com/alecthomas/kong"
"github.com/charmbracelet/log"
"github.com/input-output-hk/catalyst-forge/cli/cmd/cmds"
"github.com/input-output-hk/catalyst-forge/cli/cmd/cmds/deploy"
"github.com/input-output-hk/catalyst-forge/cli/cmd/cmds/module"
"github.com/input-output-hk/catalyst-forge/cli/cmd/cmds/release"
"github.com/input-output-hk/catalyst-forge/cli/pkg/run"
"github.com/input-output-hk/catalyst-forge/lib/project/blueprint"
"github.com/input-output-hk/catalyst-forge/lib/project/deployment"
"github.com/input-output-hk/catalyst-forge/lib/project/project"
"github.com/input-output-hk/catalyst-forge/lib/project/secrets"
Expand All @@ -32,15 +35,17 @@ type GlobalArgs struct {
var cli struct {
GlobalArgs

Dump cmds.DumpCmd `cmd:"" help:"Dumps a project's blueprint to JSON."`
CI cmds.CICmd `cmd:"" help:"Simulate a CI run."`
Mod module.ModuleCmd `kong:"cmd" help:"Commands for working with deployment modules."`
Release cmds.ReleaseCmd `cmd:"" help:"Release a project."`
Run cmds.RunCmd `cmd:"" help:"Run an Earthly target."`
Scan cmds.ScanCmd `cmd:"" help:"Scan for Earthfiles."`
Secret cmds.SecretCmd `cmd:"" help:"Manage secrets."`
Validate cmds.ValidateCmd `cmd:"" help:"Validates a project."`
Version VersionCmd `cmd:"" help:"Print the version."`
Deployments deploy.DeployCmd `cmd:"" help:"Commands for working with deployments."`
Dump cmds.DumpCmd `cmd:"" help:"Dumps a project's blueprint to JSON."`
CI cmds.CICmd `cmd:"" help:"Simulate a CI run."`
Mod module.ModuleCmd `kong:"cmd" help:"Commands for working with deployment modules."`
Release cmds.ReleaseCmd `cmd:"" help:"Release a project."`
Releases release.ReleaseCmd `cmd:"" help:"Commands for dealing with Foundry releases."`
Run cmds.RunCmd `cmd:"" help:"Run an Earthly target."`
Scan cmds.ScanCmd `cmd:"" help:"Scan for Earthfiles."`
Secret cmds.SecretCmd `cmd:"" help:"Manage secrets."`
Validate cmds.ValidateCmd `cmd:"" help:"Validates a project."`
Version VersionCmd `cmd:"" help:"Print the version."`

InstallCompletions kongplete.InstallCompletions `cmd:"" help:"install shell completions"`
}
Expand Down Expand Up @@ -92,15 +97,20 @@ func Run() int {
logger := slog.New(handler)
store := secrets.NewDefaultSecretStore()
cc := cuecontext.New()
loader := project.NewDefaultProjectLoader(cc, store, logger)
w := walker.NewDefaultFSWalker(logger)
rw := walker.NewDefaultFSReverseWalker(logger)
bl := blueprint.NewDefaultBlueprintLoader(cc, logger)
pl := project.NewDefaultProjectLoader(cc, store, logger)
runctx := run.RunContext{
BlueprintLoader: &bl,
CI: cli.GlobalArgs.CI,
CueCtx: cc,
FSWalker: walker.NewDefaultFSWalker(logger),
ReverseWalker: &rw,
Walker: &w,
Local: cli.GlobalArgs.Local,
Logger: logger,
ManifestGeneratorStore: deployment.NewDefaultManifestGeneratorStore(),
ProjectLoader: &loader,
ProjectLoader: &pl,
SecretStore: store,
Verbose: cli.GlobalArgs.Verbose,
}
Expand Down
Loading