diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 524f518..63594e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,12 +41,12 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Forge - uses: input-output-hk/catalyst-forge/actions/install@master + uses: input-output-hk/catalyst-forge/actions/install@adds-cue-release if: ${{ inputs.forge_version != 'local' }} with: version: ${{ inputs.forge_version }} - name: Install Local Forge - uses: input-output-hk/catalyst-forge/actions/install-local@master + uses: input-output-hk/catalyst-forge/actions/install-local@adds-cue-release if: ${{ inputs.forge_version == 'local' }} with: earthly_token: ${{ secrets.earthly_token }} @@ -61,14 +61,14 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup CI - uses: input-output-hk/catalyst-forge/actions/setup@master + uses: input-output-hk/catalyst-forge/actions/setup@adds-cue-release with: skip_docker: 'true' skip_github: 'true' skip_earthly: ${{ steps.local.outputs.skip }} - name: Discovery id: discovery - uses: input-output-hk/catalyst-forge/actions/discovery@master + uses: input-output-hk/catalyst-forge/actions/discovery@adds-cue-release with: filters: | ${{ env.FORGE_REGEX_CHECK }} @@ -80,7 +80,7 @@ jobs: ${{ env.FORGE_REGEX_PUBLISH }} check: - uses: input-output-hk/catalyst-forge/.github/workflows/run.yml@master + uses: input-output-hk/catalyst-forge/.github/workflows/run.yml@adds-cue-release needs: [discover] if: (fromJson(needs.discover.outputs.earthfiles)['^check(-.*)?$'] != null) && !failure() && !cancelled() with: @@ -92,7 +92,7 @@ jobs: earthly_token: ${{ secrets.earthly_token }} build: - uses: input-output-hk/catalyst-forge/.github/workflows/run.yml@master + uses: input-output-hk/catalyst-forge/.github/workflows/run.yml@adds-cue-release needs: [discover, check] if: (fromJson(needs.discover.outputs.earthfiles)['^build(-.*)?$'] != null) && !failure() && !cancelled() with: @@ -104,7 +104,7 @@ jobs: earthly_token: ${{ secrets.earthly_token }} package: - uses: input-output-hk/catalyst-forge/.github/workflows/run.yml@master + uses: input-output-hk/catalyst-forge/.github/workflows/run.yml@adds-cue-release needs: [discover, check, build] if: (fromJson(needs.discover.outputs.earthfiles)['^package(-.*)?$'] != null) && !failure() && !cancelled() with: @@ -116,7 +116,7 @@ jobs: earthly_token: ${{ secrets.earthly_token }} test: - uses: input-output-hk/catalyst-forge/.github/workflows/run.yml@master + uses: input-output-hk/catalyst-forge/.github/workflows/run.yml@adds-cue-release needs: [discover, check, build, package] if: (fromJson(needs.discover.outputs.earthfiles)['^test(-.*)?$'] != null) && !failure() && !cancelled() with: @@ -128,7 +128,7 @@ jobs: earthly_token: ${{ secrets.earthly_token }} docs: - uses: input-output-hk/catalyst-forge/.github/workflows/docs.yml@master + uses: input-output-hk/catalyst-forge/.github/workflows/docs.yml@adds-cue-release needs: [discover, check, build, test] if: (fromJson(needs.discover.outputs.earthfiles)['^docs(-.*)?$'] != null) && !failure() && !cancelled() with: @@ -138,7 +138,7 @@ jobs: earthly_token: ${{ secrets.earthly_token }} release: - uses: input-output-hk/catalyst-forge/.github/workflows/release.yml@master + uses: input-output-hk/catalyst-forge/.github/workflows/release.yml@adds-cue-release needs: [discover, check, build, test] if: (fromJson(needs.discover.outputs.releases)[0] != null) && !failure() && !cancelled() with: @@ -150,7 +150,7 @@ jobs: earthly_token: ${{ secrets.earthly_token }} deploy: - uses: input-output-hk/catalyst-forge/.github/workflows/deploy.yml@master + uses: input-output-hk/catalyst-forge/.github/workflows/deploy.yml@adds-cue-release needs: [discover, check, build, test, release] if: (fromJson(needs.discover.outputs.deployments)[0] != null) && github.ref == format('refs/heads/{0}', github.event.repository.default_branch) && !failure() && !cancelled() with: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 026cd7a..16ca908 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,12 +41,12 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Forge - uses: input-output-hk/catalyst-forge/actions/install@master + uses: input-output-hk/catalyst-forge/actions/install@adds-cue-release if: ${{ inputs.forge_version != 'local' }} with: version: ${{ inputs.forge_version }} - name: Install Local Forge - uses: input-output-hk/catalyst-forge/actions/install-local@master + uses: input-output-hk/catalyst-forge/actions/install-local@adds-cue-release if: ${{ inputs.forge_version == 'local' }} with: earthly_token: ${{ secrets.earthly_token }} @@ -61,11 +61,11 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup CI - uses: input-output-hk/catalyst-forge/actions/setup@master + uses: input-output-hk/catalyst-forge/actions/setup@adds-cue-release with: skip_earthly: ${{ steps.local.outputs.skip }} - name: Deploy - uses: input-output-hk/catalyst-forge/actions/run@master + uses: input-output-hk/catalyst-forge/actions/run@adds-cue-release with: command: deploy push args: ${{ matrix.deployment }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 80361ce..4fdc078 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -44,12 +44,12 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Forge - uses: input-output-hk/catalyst-forge/actions/install@master + uses: input-output-hk/catalyst-forge/actions/install@adds-cue-release if: ${{ inputs.forge_version != 'local' }} with: version: ${{ inputs.forge_version }} - name: Install Local Forge - uses: input-output-hk/catalyst-forge/actions/install-local@master + uses: input-output-hk/catalyst-forge/actions/install-local@adds-cue-release if: ${{ inputs.forge_version == 'local' }} with: earthly_token: ${{ secrets.earthly_token }} @@ -64,11 +64,11 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup CI - uses: input-output-hk/catalyst-forge/actions/setup@master + uses: input-output-hk/catalyst-forge/actions/setup@adds-cue-release with: skip_earthly: ${{ steps.local.outputs.skip }} - name: Run - uses: input-output-hk/catalyst-forge/actions/run@master + uses: input-output-hk/catalyst-forge/actions/run@adds-cue-release with: command: run args: --artifact ${{ env.OUTPUT }} ${{ matrix.earthfile }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 68f5045..a75845e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,12 +45,12 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Forge - uses: input-output-hk/catalyst-forge/actions/install@master + uses: input-output-hk/catalyst-forge/actions/install@adds-cue-release if: ${{ inputs.forge_version != 'local' }} with: version: ${{ inputs.forge_version }} - name: Install Local Forge - uses: input-output-hk/catalyst-forge/actions/install-local@master + uses: input-output-hk/catalyst-forge/actions/install-local@adds-cue-release if: ${{ inputs.forge_version == 'local' }} with: earthly_token: ${{ secrets.earthly_token }} @@ -65,11 +65,11 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup CI - uses: input-output-hk/catalyst-forge/actions/setup@master + uses: input-output-hk/catalyst-forge/actions/setup@adds-cue-release with: skip_earthly: ${{ steps.local.outputs.skip }} - name: Release - uses: input-output-hk/catalyst-forge/actions/run@master + uses: input-output-hk/catalyst-forge/actions/run@adds-cue-release with: command: release args: ${{ matrix.release.project }} ${{ matrix.release.name }} diff --git a/.github/workflows/run.yml b/.github/workflows/run.yml index 2556a60..946645c 100644 --- a/.github/workflows/run.yml +++ b/.github/workflows/run.yml @@ -42,12 +42,12 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install Forge - uses: input-output-hk/catalyst-forge/actions/install@master + uses: input-output-hk/catalyst-forge/actions/install@adds-cue-release if: ${{ inputs.forge_version != 'local' }} with: version: ${{ inputs.forge_version }} - name: Install Local Forge - uses: input-output-hk/catalyst-forge/actions/install-local@master + uses: input-output-hk/catalyst-forge/actions/install-local@adds-cue-release if: ${{ inputs.forge_version == 'local' }} with: earthly_token: ${{ secrets.earthly_token }} @@ -62,11 +62,11 @@ jobs: echo "skip=false" >> $GITHUB_OUTPUT fi - name: Setup CI - uses: input-output-hk/catalyst-forge/actions/setup@master + uses: input-output-hk/catalyst-forge/actions/setup@adds-cue-release with: skip_earthly: ${{ steps.local.outputs.skip }} - name: Run - uses: input-output-hk/catalyst-forge/actions/run@master + uses: input-output-hk/catalyst-forge/actions/run@adds-cue-release with: command: run args: ${{ matrix.earthfile }} diff --git a/actions/setup/action.yml b/actions/setup/action.yml index c07259f..5ef35ab 100644 --- a/actions/setup/action.yml +++ b/actions/setup/action.yml @@ -9,6 +9,10 @@ inputs: description: If true, skip authenticating with AWS and configuring ECR required: false default: "false" + skip_cue: + description: If true, skips installing CUE CLI if the provider is configured + required: false + default: "false" skip_docker: description: If true, skip authenticating to DockerHub skip_earthly: @@ -197,4 +201,28 @@ runs: uses: stefanprodan/timoni/actions/setup@main if: steps.timoni.outputs.install && steps.timoni.conclusion == 'success' with: - version: ${{ steps.timoni.outputs.version }} \ No newline at end of file + version: ${{ steps.timoni.outputs.version }} + + # CUE Provider + - name: Get CUE provider configuration + id: cue + if: inputs.skip_cue == 'false' + shell: bash + run: | + echo "==== CUE Setup =====" + BP=$(forge dump .) + + CUE=$(echo "$BP" | jq -r .global.ci.providers.cue.install) + if [[ "$TIMONI" == "true" ]]; then + INSTALL=1 + VERSION=$(echo "$BP" | jq -r .global.ci.providers.cue.version) + echo "install=$INSTALL" >> $GITHUB_OUTPUT + echo "version=$VERSION" >> $GITHUB_OUTPUT + else + echo "Not installing CUE CLI" + fi + - name: Install CUE + uses: cue-lang/setup-cue@v1.0.0 + if: steps.cue.outputs.install && steps.cue.conclusion == 'success' + with: + version: v${{ steps.cue.outputs.version }} \ No newline at end of file diff --git a/blueprint.cue b/blueprint.cue index 4704ccf..08b28d2 100644 --- a/blueprint.cue +++ b/blueprint.cue @@ -17,6 +17,12 @@ global: { role: "arn:aws:iam::332405224602:role/ci" } + cue: { + install: true + registries: [aws.registry] + version: "0.11.0" + } + docker: credentials: { provider: "aws" path: "global/ci/docker" diff --git a/cli/pkg/release/providers/cue.go b/cli/pkg/release/providers/cue.go new file mode 100644 index 0000000..7a976ac --- /dev/null +++ b/cli/pkg/release/providers/cue.go @@ -0,0 +1,68 @@ +package providers + +import ( + "fmt" + "log/slog" + + "github.com/input-output-hk/catalyst-forge/cli/pkg/events" + "github.com/input-output-hk/catalyst-forge/cli/pkg/executor" + "github.com/input-output-hk/catalyst-forge/cli/pkg/run" + "github.com/input-output-hk/catalyst-forge/lib/project/project" + "github.com/input-output-hk/catalyst-forge/lib/project/schema" +) + +const CUE_BINARY = "cue" + +type CueReleaserConfig struct { + Container string `json:"container"` + Tag string `json:"tag"` +} + +type CueReleaser struct { + config CueReleaserConfig + cue executor.WrappedExecuter + force bool + handler events.EventHandler + logger *slog.Logger + project project.Project + release schema.Release + releaseName string +} + +func (r *CueReleaser) Release() error { + return nil +} + +func NewCueReleaser(ctx run.RunContext, + project project.Project, + name string, + force bool, +) (*CueReleaser, error) { + release, ok := project.Blueprint.Project.Release[name] + if !ok { + return nil, fmt.Errorf("unknown release: %s", name) + } + + exec := executor.NewLocalExecutor(ctx.Logger) + if _, ok := exec.LookPath(CUE_BINARY); ok != nil { + return nil, fmt.Errorf("failed to find cue binary: %w", ok) + } + + var config CueReleaserConfig + if err := parseConfig(&project, name, &config); err != nil { + return nil, fmt.Errorf("failed to parse release config: %w", err) + } + + cue := executor.NewLocalWrappedExecutor(exec, "timoni") + handler := events.NewDefaultEventHandler(ctx.Logger) + return &CueReleaser{ + config: config, + cue: cue, + force: force, + handler: &handler, + logger: ctx.Logger, + project: project, + release: release, + releaseName: name, + }, nil +} diff --git a/cli/pkg/release/releaser.go b/cli/pkg/release/releaser.go index 82bb48f..2ef68c0 100644 --- a/cli/pkg/release/releaser.go +++ b/cli/pkg/release/releaser.go @@ -11,6 +11,7 @@ import ( type ReleaserType string const ( + ReleaserTypeCue ReleaserType = "cue" ReleaserTypeDocker ReleaserType = "docker" ReleaserTypeGithub ReleaserType = "github" ReleaserTypeTimoni ReleaserType = "timoni" @@ -44,6 +45,9 @@ func (r *ReleaserStore) GetReleaser( func NewDefaultReleaserStore() *ReleaserStore { return &ReleaserStore{ releasers: map[ReleaserType]ReleaserFactory{ + ReleaserTypeCue: func(ctx run.RunContext, project project.Project, name string, force bool) (Releaser, error) { + return providers.NewCueReleaser(ctx, project, name, force) + }, ReleaserTypeDocker: func(ctx run.RunContext, project project.Project, name string, force bool) (Releaser, error) { return providers.NewDockerReleaser(ctx, project, name, force) }, diff --git a/lib/project/schema/_embed/schema.cue b/lib/project/schema/_embed/schema.cue index 953ade5..cbda267 100644 --- a/lib/project/schema/_embed/schema.cue +++ b/lib/project/schema/_embed/schema.cue @@ -59,6 +59,10 @@ package schema // +optional aws?: #ProviderAWS @go(AWS) + // CUE contains the configuration for the CUE provider. + // +optional + cue?: #ProviderCue @go(CUE) + // Docker contains the configuration for the DockerHub provider. // +optional docker?: #ProviderDocker @go(Docker) @@ -93,6 +97,20 @@ package schema registry?: null | string @go(Registry,*string) } +// ProviderCue contains the configuration for the CUE provider. +#ProviderCue: { + // Install contains whether to install CUE in the CI environment. + // +optional + install?: null | bool @go(Install,*bool) + + // Registries contains the registries to use for publishing CUE modules + registries: [...string] @go(Registries,[]string) + + // The version of CUE to use in CI. + // +optional + version?: string @go(Version) +} + // ProviderDocker contains the configuration for the DockerHub provider. #ProviderDocker: { // Credentials contains the credentials to use for DockerHub diff --git a/lib/project/schema/providers.go b/lib/project/schema/providers.go index b5db855..cb05be4 100644 --- a/lib/project/schema/providers.go +++ b/lib/project/schema/providers.go @@ -6,6 +6,10 @@ type Providers struct { // +optional AWS ProviderAWS `json:"aws"` + // CUE contains the configuration for the CUE provider. + // +optional + CUE ProviderCue `json:"cue"` + // Docker contains the configuration for the DockerHub provider. // +optional Docker ProviderDocker `json:"docker"` @@ -40,6 +44,20 @@ type ProviderAWS struct { Registry *string `json:"registry"` } +// ProviderCue contains the configuration for the CUE provider. +type ProviderCue struct { + // Install contains whether to install CUE in the CI environment. + // +optional + Install *bool `json:"install"` + + // Registries contains the registries to use for publishing CUE modules + Registries []string `json:"registries"` + + // The version of CUE to use in CI. + // +optional + Version string `json:"version"` +} + // ProviderDocker contains the configuration for the DockerHub provider. type ProviderDocker struct { // Credentials contains the credentials to use for DockerHub diff --git a/lib/project/schema/providers_go_gen.cue b/lib/project/schema/providers_go_gen.cue index 28a9400..cf49153 100644 --- a/lib/project/schema/providers_go_gen.cue +++ b/lib/project/schema/providers_go_gen.cue @@ -10,6 +10,10 @@ package schema // +optional aws?: #ProviderAWS @go(AWS) + // CUE contains the configuration for the CUE provider. + // +optional + cue?: #ProviderCue @go(CUE) + // Docker contains the configuration for the DockerHub provider. // +optional docker?: #ProviderDocker @go(Docker) @@ -44,6 +48,20 @@ package schema registry?: null | string @go(Registry,*string) } +// ProviderCue contains the configuration for the CUE provider. +#ProviderCue: { + // Install contains whether to install CUE in the CI environment. + // +optional + install?: null | bool @go(Install,*bool) + + // Registries contains the registries to use for publishing CUE modules + registries: [...string] @go(Registries,[]string) + + // The version of CUE to use in CI. + // +optional + version?: string @go(Version) +} + // ProviderDocker contains the configuration for the DockerHub provider. #ProviderDocker: { // Credentials contains the credentials to use for DockerHub