Skip to content

Commit 71b9e2c

Browse files
authored
refactor: deprecates Earthly cloud support and adds remote satellite support (#173)
1 parent 99c7769 commit 71b9e2c

File tree

17 files changed

+578
-114
lines changed

17 files changed

+578
-114
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ on:
2222
required: false
2323
type: boolean
2424
default: false
25-
secrets:
26-
earthly_token:
27-
description: Optional Earthly token used to login to Earthly cloud during local builds of Forge CLI
28-
required: false
2925

3026
env:
3127
FORGE_REGEX_CHECK: ^check(-.*)?$
@@ -52,10 +48,9 @@ jobs:
5248
with:
5349
version: ${{ inputs.forge_version }}
5450
- name: Install Local Forge
51+
id: install-local
5552
uses: input-output-hk/catalyst-forge/actions/install-local@master
5653
if: ${{ inputs.forge_version == 'local' }}
57-
with:
58-
earthly_token: ${{ secrets.earthly_token }}
5954
- name: Check forge version
6055
id: local
6156
run: |
@@ -71,7 +66,8 @@ jobs:
7166
with:
7267
skip_docker: 'true'
7368
skip_github: 'true'
74-
skip_earthly: ${{ steps.local.outputs.skip }}
69+
skip_earthly_install: ${{ steps.install-local.outputs.cache-hit == false }}
70+
skip_earthly_satellite: ${{ steps.install-local.outputs.cache-hit == false }}
7571
- name: Discovery
7672
id: discovery
7773
uses: input-output-hk/catalyst-forge/actions/discovery@master

.github/workflows/dogfood.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,4 @@ jobs:
1717
with:
1818
forge_version: local
1919
verbosity: debug
20-
nightly: true
21-
secrets:
22-
earthly_token: ${{ secrets.EARTHLY_TOKEN }}
20+
nightly: true

.github/workflows/run.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ jobs:
4747
with:
4848
version: ${{ inputs.forge_version }}
4949
- name: Install Local Forge
50+
id: install-local
5051
uses: input-output-hk/catalyst-forge/actions/install-local@master
5152
if: ${{ inputs.forge_version == 'local' }}
5253
with:
@@ -64,7 +65,8 @@ jobs:
6465
- name: Setup CI
6566
uses: input-output-hk/catalyst-forge/actions/setup@master
6667
with:
67-
skip_earthly: ${{ steps.local.outputs.skip }}
68+
skip_earthly_install: ${{ steps.install-local.outputs.cache-hit == false }}
69+
skip_earthly_satellite: ${{ steps.install-local.outputs.cache-hit == false }}
6870
- name: Run
6971
uses: input-output-hk/catalyst-forge/actions/run@master
7072
with:

actions/install-local/action.yml

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,87 @@
11
name: Install local forge CLI
22
description: Installs a local version of the forge CLI
3-
inputs:
4-
earthly_token:
5-
description: Earthly token used to login to Earthly cloud for local build
6-
required: true
73

84
runs:
95
using: composite
106
steps:
7+
- name: Cache binary
8+
id: cache-binary
9+
uses: actions/cache@v4
10+
with:
11+
path: /usr/local/bin/forge
12+
key: ${{ runner.os }}-${{ github.sha }}
1113
- shell: bash
14+
if: steps.cache-binary.outputs.cache-hit == false
1215
run: echo "Building Forge CLI locally..."
1316
- name: Cache Earthly binary
1417
id: cache-earthly
18+
if: steps.cache-binary.outputs.cache-hit == false
1519
uses: actions/cache@v4
1620
with:
1721
path: /usr/local/bin/earthly
1822
key: ${{ runner.os }}
1923
- name: Install Earthly
20-
if: steps.cache-earthly.outputs.cache-hit == false
24+
if: steps.cache-earthly.outputs.cache-hit == false && steps.cache-binary.outputs.cache-hit == false
2125
shell: bash
2226
run: |
2327
wget -q https://github.com/earthly/earthly/releases/latest/download/earthly-linux-amd64 -O /usr/local/bin/earthly
2428
chmod +x /usr/local/bin/earthly
2529
/usr/local/bin/earthly bootstrap
26-
- name: Login to Earthly Cloud
30+
- name: Install CUE
31+
uses: cue-lang/[email protected]
32+
if: steps.cache-binary.outputs.cache-hit == false
33+
with:
34+
version: latest
35+
- name: Get AWS configuration
36+
id: aws
2737
if: steps.cache-binary.outputs.cache-hit == false
2838
shell: bash
2939
run: |
30-
earthly account login --token ${{ inputs.earthly_token }}
31-
earthly org select Catalyst
32-
- name: Cache binary
33-
id: cache-binary
34-
uses: actions/cache@v4
40+
AWS=$(cue export -e global.ci.providers.aws ./blueprint.cue)
41+
REGION=$(echo "$AWS" | jq -r .region)
42+
ROLE=$(echo "$AWS" | jq -r .role)
43+
44+
echo "region=$REGION" >> $GITHUB_OUTPUT
45+
echo "role=$ROLE" >> $GITHUB_OUTPUT
46+
- name: Login to AWS
47+
uses: aws-actions/configure-aws-credentials@v4
48+
if: steps.cache-binary.outputs.cache-hit == false
3549
with:
36-
path: /usr/local/bin/forge
37-
key: ${{ runner.os }}-${{ github.sha }}
50+
aws-region: ${{ steps.aws.outputs.region }}
51+
role-to-assume: ${{ steps.aws.outputs.role }}
52+
- name: Configure Earthly satellite credentials
53+
if: steps.cache-binary.outputs.cache-hit == false
54+
shell: bash
55+
run: |
56+
mkdir -p "$HOME/.earthly"
57+
58+
EARTHLY=$(cue export -e global.ci.providers.earthly.satellite.credentials ./blueprint.cue)
59+
SECRET_ID=$(echo "$EARTHLY" | jq -r .path)
60+
61+
SECRET=$(aws secretsmanager get-secret-value --secret-id "$SECRET_ID")
62+
echo "$SECRET" | jq -r .SecretString | jq -r .ca_certificate | base64 -d > ~/.earthly/ca.pem
63+
echo "$SECRET" | jq -r .SecretString | jq -r .certificate | base64 -d > ~/.earthly/cert.pem
64+
echo "$SECRET" | jq -r .SecretString | jq -r .private_key | base64 -d > ~/.earthly/key.pem
65+
66+
cat <<EOF > "$HOME/.earthly/config.yml"
67+
global:
68+
buildkit_host: $(echo "$SECRET" | jq -r .SecretString | jq -r .host)
69+
tlsca: ca.pem
70+
tlscert: cert.pem
71+
tlskey: key.pem
72+
EOF
73+
74+
echo "::add-mask::$(echo "$SECRET" | jq -r .SecretString | jq -r .host)"
3875
- name: Build Forge CLI
3976
if: steps.cache-binary.outputs.cache-hit == false
4077
shell: bash
4178
run: |
42-
echo "::group::Forge CLI Earthly Build"
43-
earthly --sat ci --artifact ./cli+build/forge /usr/local/bin/forge
44-
echo "::endgroup::"
79+
earthly --artifact ./cli+build/forge /usr/local/bin/forge
80+
- name: Set output cache-hit
81+
shell: bash
82+
run: echo "cache-hit=${{ steps.cache-binary.outputs.cache-hit }}" >> $GITHUB_OUTPUT
83+
84+
outputs:
85+
cache-hit:
86+
description: "Whether the forge binary was restored from cache"
87+
value: ${{ steps.cache-binary.outputs.cache-hit }}

actions/setup/action.yml

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ inputs:
1717
description: If true, skip authenticating to DockerHub
1818
required: false
1919
default: "false"
20-
skip_earthly:
21-
description: If true, skip installing Earthly and authenticating to Earthly Cloud
20+
skip_earthly_install:
21+
description: If true, skip installing Earthly
22+
required: false
23+
default: "false"
24+
skip_earthly_satellite:
25+
description: If true, skip adding authentication for the remote Earthly satellite
2226
required: false
2327
default: "false"
2428
skip_github:
@@ -133,7 +137,7 @@ runs:
133137

134138
# Earthly Provider
135139
- name: Get Earthly provider configuration
136-
if: inputs.skip_earthly == 'false'
140+
if: inputs.skip_earthly_install == 'false' && inputs.skip_earthly_satellite == 'false'
137141
id: earthly
138142
shell: bash
139143
run: |
@@ -144,40 +148,30 @@ runs:
144148
145149
EARTHLY=$(echo "$BP" | jq -r .global.ci.providers.earthly)
146150
if [[ "$EARTHLY" != "null" ]]; then
147-
ORG=$(echo "$BP" | jq -r .global.ci.providers.earthly.org)
148151
VERSION=$(echo "$BP" | jq -r .global.ci.providers.earthly.version)
149152
150-
echo "org=$ORG" >> $GITHUB_OUTPUT
151-
152-
EARTHLY_CREDS=$(echo "$BP" | jq -r .global.ci.providers.earthly.credentials)
153-
if [[ "$EARTHLY_CREDS" != "null" ]]; then
154-
SECRET=$(forge secret get --project . global.ci.providers.earthly.credentials)
155-
TOKEN=$(echo "$SECRET" | jq -r .token)
156-
157-
if [[ "$TOKEN" == "null" ]]; then
158-
echo "Error: the earthly provider secret must map the secret value to 'token'"
159-
exit 1
160-
fi
161-
162-
echo "::add-mask::$TOKEN"
163-
echo "token=$TOKEN" >> $GITHUB_OUTPUT
153+
SATELLITE_CREDS=$(echo "$BP" | jq -r .global.ci.providers.earthly.satellite.credentials)
154+
if [[ "$SATELLITE_CREDS" != "null" ]]; then
155+
CONFIG_SAT="true"
164156
else
165-
echo "No configuration found for Earthly Cloud provider"
157+
CONFIG_SAT="false"
158+
echo "No configuration found for remote Earthly satellite"
166159
fi
167160
else
168-
echo "No configuration found for Earthly Cloud provider"
161+
echo "No configuration found for Earthly provider"
169162
fi
170163
164+
echo "sat=$CONFIG_SAT" >> GITHUB_OUTPUT
171165
echo "version=$VERSION" >> $GITHUB_OUTPUT
172166
- name: Cache Earthly binary
173167
id: cache-binary
174168
uses: actions/cache@v4
175-
if: inputs.skip_earthly == 'false'
169+
if: inputs.skip_earthly_install == 'false'
176170
with:
177171
path: /usr/local/bin/earthly
178172
key: ${{ runner.os }}-${{ steps.earthly.outputs.version }}
179173
- name: Install Earthly
180-
if: inputs.skip_earthly == 'false' && steps.cache-binary.outputs.cache-hit == false
174+
if: inputs.skip_earthly_install == 'false' && steps.cache-binary.outputs.cache-hit == false
181175
shell: bash
182176
run: |
183177
if [[ "${{ steps.earthly.outputs.version }}" == "latest" ]]; then
@@ -188,16 +182,12 @@ runs:
188182
189183
chmod +x /usr/local/bin/earthly
190184
/usr/local/bin/earthly bootstrap
191-
# - name: Login to Earthly Cloud
192-
# if: steps.earthly.outputs.token != '' && steps.earthly.conclusion == 'success'
193-
# shell: bash
194-
# run: |
195-
# earthly account login --token "${{ steps.earthly.outputs.token }}"
196-
# - name: Set Earthly organization
197-
# if: steps.earthly.outputs.token != '' && steps.earthly.conclusion == 'success'
198-
# shell: bash
199-
# run: |
200-
# earthly org select "${{ steps.earthly.outputs.org }}"
185+
- name: Configure Earthly satellite credentials
186+
if: inputs.skip_earthly_satellite == 'false' && steps.earthly.conclusion == 'success'
187+
shell: bash
188+
run: |
189+
rm -rf "$HOME/.earthly"
190+
forge configure-satellite -vvv --ci
201191
202192
# Timoni Provider
203193
- name: Get Timoni provider configuration

blueprint.cue

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,11 @@ global: {
3333
}
3434

3535
earthly: {
36-
credentials: {
36+
satellite: credentials: {
3737
provider: "aws"
38-
path: "global/ci/earthly"
38+
path: "global/ci/ci-tls"
3939
}
40-
org: "Catalyst"
41-
satellite: "ci"
42-
version: "0.8.15"
40+
version: "0.8.15"
4341
}
4442

4543
git: credentials: {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package cmds
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/input-output-hk/catalyst-forge/cli/pkg/earthly/satellite"
9+
"github.com/input-output-hk/catalyst-forge/cli/pkg/run"
10+
"github.com/input-output-hk/catalyst-forge/lib/tools/fs/billy"
11+
"github.com/input-output-hk/catalyst-forge/lib/tools/git"
12+
"github.com/input-output-hk/catalyst-forge/lib/tools/walker"
13+
)
14+
15+
type ConfigureSatelliteCmd struct {
16+
Path string `short:"p" help:"Path to place the Earthly config and certificates."`
17+
}
18+
19+
func (c *ConfigureSatelliteCmd) Run(ctx run.RunContext) error {
20+
fs := billy.NewBaseOsFS()
21+
cwd, err := os.Getwd()
22+
if err != nil {
23+
return fmt.Errorf("failed to get current working directory: %w", err)
24+
}
25+
26+
ctx.Logger.Debug("Finding git root", "path", cwd)
27+
w := walker.NewCustomReverseFSWalker(fs, ctx.Logger)
28+
gitRoot, err := git.FindGitRoot(cwd, &w)
29+
if err != nil {
30+
return fmt.Errorf("failed to find git root: %w", err)
31+
}
32+
ctx.Logger.Debug("Git root found", "path", gitRoot)
33+
34+
ctx.Logger.Debug("Loading project", "path", gitRoot)
35+
project, err := ctx.ProjectLoader.Load(gitRoot)
36+
if err != nil {
37+
return err
38+
}
39+
40+
if c.Path == "" {
41+
home, err := os.UserHomeDir()
42+
if err != nil {
43+
return fmt.Errorf("failed to get user's home directory: %w", err)
44+
}
45+
46+
c.Path = filepath.Join(home, ".earthly")
47+
}
48+
49+
ctx.Logger.Info("Configuring satellite", "path", c.Path)
50+
satellite := satellite.NewEarthlySatellite(
51+
&project,
52+
c.Path,
53+
ctx.Logger,
54+
satellite.WithSecretStore(ctx.SecretStore),
55+
satellite.WithCI(ctx.CI),
56+
)
57+
if err := satellite.Configure(); err != nil {
58+
return fmt.Errorf("failed to configure satellite: %w", err)
59+
}
60+
61+
return nil
62+
}

cli/cmd/main.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,16 @@ type GlobalArgs struct {
3232
var cli struct {
3333
GlobalArgs
3434

35-
Dump cmds.DumpCmd `cmd:"" help:"Dumps a project's blueprint to JSON."`
36-
CI cmds.CICmd `cmd:"" help:"Simulate a CI run."`
37-
Mod module.ModuleCmd `kong:"cmd" help:"Commands for working with deployment modules."`
38-
Release cmds.ReleaseCmd `cmd:"" help:"Release a project."`
39-
Run cmds.RunCmd `cmd:"" help:"Run an Earthly target."`
40-
Scan cmds.ScanCmd `cmd:"" help:"Scan for Earthfiles."`
41-
Secret cmds.SecretCmd `cmd:"" help:"Manage secrets."`
42-
Validate cmds.ValidateCmd `cmd:"" help:"Validates a project."`
43-
Version VersionCmd `cmd:"" help:"Print the version."`
35+
Dump cmds.DumpCmd `cmd:"" help:"Dumps a project's blueprint to JSON."`
36+
CI cmds.CICmd `cmd:"" help:"Simulate a CI run."`
37+
ConfigureSatellite cmds.ConfigureSatelliteCmd `cmd:"" help:"Configure the local system to use a remote Earthly Satellite."`
38+
Mod module.ModuleCmd `kong:"cmd" help:"Commands for working with deployment modules."`
39+
Release cmds.ReleaseCmd `cmd:"" help:"Release a project."`
40+
Run cmds.RunCmd `cmd:"" help:"Run an Earthly target."`
41+
Scan cmds.ScanCmd `cmd:"" help:"Scan for Earthfiles."`
42+
Secret cmds.SecretCmd `cmd:"" help:"Manage secrets."`
43+
Validate cmds.ValidateCmd `cmd:"" help:"Validates a project."`
44+
Version VersionCmd `cmd:"" help:"Print the version."`
4445

4546
InstallCompletions kongplete.InstallCompletions `cmd:"" help:"install shell completions"`
4647
}

cli/pkg/earthly/earthly_test.go

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,15 +164,6 @@ func TestEarthlyExecutor_buildArguments(t *testing.T) {
164164
platform: GetBuildPlatform(),
165165
expect: []string{"--platform", GetBuildPlatform(), "--allow-privileged", "/test/dir+foo"},
166166
},
167-
{
168-
name: "with satellite",
169-
e: NewEarthlyExecutor("/test/dir", "foo", nil, secrets.SecretStore{},
170-
testutils.NewNoopLogger(),
171-
WithSatellite("satellite"),
172-
),
173-
platform: GetBuildPlatform(),
174-
expect: []string{"--platform", GetBuildPlatform(), "--sat", "satellite", "/test/dir+foo"},
175-
},
176167
}
177168

178169
for _, tt := range tests {

0 commit comments

Comments
 (0)