Skip to content

Commit c9a4b05

Browse files
committed
feat(ibmcloud): add GitHub Actions runner support for IBM Power and IBM Z
1 parent a2f7a23 commit c9a4b05

14 files changed

Lines changed: 197 additions & 62 deletions

File tree

cmd/mapt/cmd/ibmcloud/hosts/ibm-power.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package hosts
22

33
import (
44
"github.com/redhat-developer/mapt/cmd/mapt/cmd/params"
5+
"github.com/redhat-developer/mapt/pkg/integrations/github"
56
"github.com/redhat-developer/mapt/pkg/integrations/gitlab"
67
maptContext "github.com/redhat-developer/mapt/pkg/manager/context"
78
ibmpower "github.com/redhat-developer/mapt/pkg/provider/ibmcloud/action/ibm-power"
@@ -43,6 +44,10 @@ func ibmPowerCreate() *cobra.Command {
4344
if err := viper.BindPFlags(cmd.Flags()); err != nil {
4445
return err
4546
}
47+
ghRunnerArgs := params.GithubRunnerArgs()
48+
if ghRunnerArgs != nil {
49+
ghRunnerArgs.Arch = &github.Ppc64le
50+
}
4651
return ibmpower.New(
4752
&maptContext.ContextArgs{
4853
Context: cmd.Context(),
@@ -52,7 +57,7 @@ func ibmPowerCreate() *cobra.Command {
5257
Debug: viper.IsSet(params.Debug),
5358
DebugLevel: viper.GetUint(params.DebugLevel),
5459
CirrusPWArgs: params.CirrusPersistentWorkerArgs(),
55-
GHRunnerArgs: params.GithubRunnerArgs(),
60+
GHRunnerArgs: ghRunnerArgs,
5661
GLRunnerArgs: params.GitLabRunnerArgs(&gitlab.Ppc64le),
5762
Tags: viper.GetStringMapString(params.Tags),
5863
},

cmd/mapt/cmd/ibmcloud/hosts/ibm-z.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package hosts
22

33
import (
44
"github.com/redhat-developer/mapt/cmd/mapt/cmd/params"
5+
"github.com/redhat-developer/mapt/pkg/integrations/github"
56
"github.com/redhat-developer/mapt/pkg/integrations/gitlab"
67
maptContext "github.com/redhat-developer/mapt/pkg/manager/context"
78
ibmz "github.com/redhat-developer/mapt/pkg/provider/ibmcloud/action/ibm-z"
@@ -43,6 +44,10 @@ func ibmZCreate() *cobra.Command {
4344
if err := viper.BindPFlags(cmd.Flags()); err != nil {
4445
return err
4546
}
47+
ghRunnerArgs := params.GithubRunnerArgs()
48+
if ghRunnerArgs != nil {
49+
ghRunnerArgs.Arch = &github.S390x
50+
}
4651
return ibmz.New(
4752
&maptContext.ContextArgs{
4853
Context: cmd.Context(),
@@ -52,7 +57,7 @@ func ibmZCreate() *cobra.Command {
5257
Debug: viper.IsSet(params.Debug),
5358
DebugLevel: viper.GetUint(params.DebugLevel),
5459
CirrusPWArgs: params.CirrusPersistentWorkerArgs(),
55-
GHRunnerArgs: params.GithubRunnerArgs(),
60+
GHRunnerArgs: ghRunnerArgs,
5661
GLRunnerArgs: params.GitLabRunnerArgs(&gitlab.S390x),
5762
Tags: viper.GetStringMapString(params.Tags),
5863
},

cmd/mapt/cmd/params/params.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,14 @@ const (
7373
CreateCmdName string = "create"
7474
DestroyCmdName string = "destroy"
7575

76-
ghActionsRunnerToken string = "ghactions-runner-token"
77-
ghActionsRunnerRepo string = "ghactions-runner-repo"
78-
ghActionsRunnerLabels string = "ghactions-runner-labels"
76+
ghActionsRunnerToken string = "ghactions-runner-token"
77+
ghActionsRunnerRepo string = "ghactions-runner-repo"
78+
ghActionsRunnerLabels string = "ghactions-runner-labels"
79+
ghActionsRunnerImageRepo string = "ghactions-runner-image-repo"
80+
// TODO: once the RHEL script is merged to https://github.com/IBM/action-runner-image-pz,
81+
// switch default from deekay2310 fork to IBM upstream.
82+
ghActionsRunnerImageRepoDefault string = "https://github.com/deekay2310/action-runner-image-pz.git"
83+
GHActionsRunnerImageRepoDesc string = "Git clone URL for the action-runner-image-pz repository, used to build the GitHub Actions runner from source on ppc64le/s390x (no official binaries exist for these architectures)"
7984

8085
cirrusPWToken string = "it-cirrus-pw-token"
8186
cirrusPWTokenDesc string = "Add mapt target as a cirrus persistent worker. The value will hold a valid token to be used by cirrus cli to join the project."
@@ -278,17 +283,18 @@ func AddGHActionsFlags(fs *pflag.FlagSet) {
278283
fs.StringP(ghActionsRunnerToken, "", "", GHActionsRunnerTokenDesc)
279284
fs.StringP(ghActionsRunnerRepo, "", "", GHActionsRunnerRepoDesc)
280285
fs.StringSlice(ghActionsRunnerLabels, nil, GHActionsRunnerLabelsDesc)
286+
fs.StringP(ghActionsRunnerImageRepo, "", ghActionsRunnerImageRepoDefault, GHActionsRunnerImageRepoDesc)
281287
}
282288

283289
func GithubRunnerArgs() *github.GithubRunnerArgs {
284290
if viper.IsSet(ghActionsRunnerToken) {
285291
return &github.GithubRunnerArgs{
286-
Token: viper.GetString(ghActionsRunnerToken),
287-
RepoURL: viper.GetString(ghActionsRunnerRepo),
288-
Labels: viper.GetStringSlice(ghActionsRunnerLabels),
289-
Platform: &github.Linux,
290-
Arch: linuxArchAsGithubActionsArch(
291-
viper.GetString(LinuxArch)),
292+
Token: viper.GetString(ghActionsRunnerToken),
293+
RepoURL: viper.GetString(ghActionsRunnerRepo),
294+
Labels: viper.GetStringSlice(ghActionsRunnerLabels),
295+
Platform: &github.Linux,
296+
Arch: linuxArchAsGithubActionsArch(viper.GetString(LinuxArch)),
297+
RunnerImageRepo: viper.GetString(ghActionsRunnerImageRepo),
292298
}
293299
}
294300
return nil
@@ -359,6 +365,10 @@ func linuxArchAsGithubActionsArch(arch string) *github.Arch {
359365
switch arch {
360366
case "x86_64":
361367
return &github.Amd64
368+
case "ppc64le":
369+
return &github.Ppc64le
370+
case "s390x":
371+
return &github.S390x
362372
}
363373
return &github.Arm64
364374
}

pkg/integrations/github/ghrunner.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,23 @@ var snippetLinux []byte
2323
//go:embed snippet-windows.ps1
2424
var snippetWindows []byte
2525

26+
//go:embed snippet-linux-ppc64le.sh
27+
var snippetLinuxPpc64le []byte
28+
29+
//go:embed snippet-linux-s390x.sh
30+
var snippetLinuxS390x []byte
31+
2632
var snippets map[Platform][]byte = map[Platform][]byte{
2733
Darwin: snippetDarwin,
2834
Linux: snippetLinux,
2935
Windows: snippetWindows,
3036
}
3137

38+
var archSnippets map[Arch][]byte = map[Arch][]byte{
39+
Ppc64le: snippetLinuxPpc64le,
40+
S390x: snippetLinuxS390x,
41+
}
42+
3243
var runnerArgs *GithubRunnerArgs
3344

3445
func Init(args *GithubRunnerArgs) {
@@ -40,17 +51,22 @@ func (args *GithubRunnerArgs) GetUserDataValues() *integrations.UserDataValues {
4051
return nil
4152
}
4253
return &integrations.UserDataValues{
43-
Name: args.Name,
44-
Token: args.Token,
45-
Labels: getLabels(),
46-
RepoURL: args.RepoURL,
47-
CliURL: downloadURL(),
54+
Name: args.Name,
55+
Token: args.Token,
56+
Labels: getLabels(),
57+
RepoURL: args.RepoURL,
58+
CliURL: downloadURL(),
59+
RunnerImageRepo: args.RunnerImageRepo,
4860
}
4961
}
5062

5163
func (args *GithubRunnerArgs) GetSetupScriptTemplate() string {
52-
templateConfig := string(snippets[*runnerArgs.Platform][:])
53-
return templateConfig
64+
if *runnerArgs.Platform == Linux && runnerArgs.Arch != nil {
65+
if archSnippet, ok := archSnippets[*runnerArgs.Arch]; ok {
66+
return string(archSnippet[:])
67+
}
68+
}
69+
return string(snippets[*runnerArgs.Platform][:])
5470
}
5571

5672
func GetRunnerArgs() *GithubRunnerArgs {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
git clone {{ .RunnerImageRepo }} /opt/action-runner-image-pz
5+
6+
cd /opt/action-runner-image-pz
7+
bash -c '. scripts/vm.sh rhel 9 minimal --skip-snap-lxd'
8+
9+
cd /opt/runner-cache
10+
export DOTNET_ROOT=/opt/dotnet
11+
export PATH=$PATH:$DOTNET_ROOT
12+
13+
./config.sh \
14+
--unattended \
15+
--disableupdate \
16+
--ephemeral \
17+
--name "{{ .Name }}" \
18+
--labels "{{ .Labels }}" \
19+
--url "{{ .RepoURL }}" \
20+
--token "{{ .Token }}"
21+
22+
nohup ./run.sh > /var/log/gh-runner.log 2>&1 &
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
git clone {{ .RunnerImageRepo }} /opt/action-runner-image-pz
5+
6+
cd /opt/action-runner-image-pz
7+
bash -c '. scripts/vm.sh ubuntu 22.04 minimal --skip-snap-lxd'
8+
9+
cd /opt/runner-cache
10+
export DOTNET_ROOT=/opt/dotnet
11+
export PATH=$PATH:$DOTNET_ROOT
12+
13+
./config.sh \
14+
--unattended \
15+
--disableupdate \
16+
--ephemeral \
17+
--name "{{ .Name }}" \
18+
--labels "{{ .Labels }}" \
19+
--url "{{ .RepoURL }}" \
20+
--token "{{ .Token }}"
21+
22+
nohup ./run.sh > /var/log/gh-runner.log 2>&1 &

pkg/integrations/github/types.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,20 @@ var (
88
Linux Platform = "linux"
99
Darwin Platform = "osx"
1010

11-
Arm64 Arch = "arm64"
12-
Amd64 Arch = "x64"
13-
Arm Arch = "arm"
11+
Arm64 Arch = "arm64"
12+
Amd64 Arch = "x64"
13+
Arm Arch = "arm"
14+
Ppc64le Arch = "ppc64le"
15+
S390x Arch = "s390x"
1416
)
1517

1618
type GithubRunnerArgs struct {
17-
Token string
18-
RepoURL string
19-
Name string
20-
Platform *Platform
21-
Arch *Arch
22-
Labels []string
23-
User string
19+
Token string
20+
RepoURL string
21+
Name string
22+
Platform *Platform
23+
Arch *Arch
24+
Labels []string
25+
User string
26+
RunnerImageRepo string
2427
}

pkg/integrations/integrations.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ import (
66
)
77

88
type UserDataValues struct {
9-
CliURL string
10-
User string
11-
Name string
12-
Token string
13-
Labels string
14-
Port string
15-
RepoURL string
16-
Executor string
17-
Unsecure bool
18-
Concurrent int
9+
CliURL string
10+
User string
11+
Name string
12+
Token string
13+
Labels string
14+
Port string
15+
RepoURL string
16+
Executor string
17+
Unsecure bool
18+
Concurrent int
19+
RunnerImageRepo string
1920
}
2021

2122
type IntegrationConfig interface {

pkg/provider/ibmcloud/action/ibm-power/cloud-config

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ write_files:
8080
content: |
8181
{{.GitLabRunnerScript}}
8282
{{- end}}
83+
{{- if .GHActionsRunnerScript}}
84+
- path: /opt/install-ghrunner.sh
85+
permissions: '0700'
86+
owner: root:root
87+
content: |
88+
{{.GHActionsRunnerScript}}
89+
{{- end}}
8390
runcmd:
8491
- systemctl enable mount-data-home.service
8592
- dnf install -y git podman policycoreutils-python-utils
@@ -98,3 +105,6 @@ runcmd:
98105
- mkdir -p /var/log/gitlab-runner
99106
- bash /opt/install-glrunner.sh
100107
{{- end}}
108+
{{- if .GHActionsRunnerScript}}
109+
- bash /opt/install-ghrunner.sh
110+
{{- end}}

pkg/provider/ibmcloud/action/ibm-power/ibm-power.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/pulumi/pulumi/sdk/v3/go/auto"
1212
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
1313
"github.com/redhat-developer/mapt/pkg/integrations"
14+
"github.com/redhat-developer/mapt/pkg/integrations/github"
1415
"github.com/redhat-developer/mapt/pkg/integrations/gitlab"
1516
"github.com/redhat-developer/mapt/pkg/integrations/otelcol"
1617
"github.com/redhat-developer/mapt/pkg/manager"
@@ -29,9 +30,10 @@ import (
2930
var CloudConfig []byte
3031

3132
type userDataValues struct {
32-
Gateway string
33-
OtelColScript string
34-
GitLabRunnerScript string
33+
Gateway string
34+
OtelColScript string
35+
GitLabRunnerScript string
36+
GHActionsRunnerScript string
3537
}
3638

3739
const (
@@ -183,6 +185,15 @@ func (r *pwRequest) deploy(ctx *pulumi.Context) error {
183185
}
184186
hasOtel := otelSet == 3
185187

188+
ghRunnerScript := ""
189+
if ghRunnerArgs := github.GetRunnerArgs(); ghRunnerArgs != nil {
190+
s, err := integrations.GetIntegrationSnippetAsCloudInitWritableFile(ghRunnerArgs, defaultUser)
191+
if err != nil {
192+
return err
193+
}
194+
ghRunnerScript = *s
195+
}
196+
186197
var piUserDataInput pulumi.StringPtrInput
187198
glRunnerArgs := gitlab.GetRunnerArgs()
188199
if glRunnerArgs != nil {
@@ -192,6 +203,7 @@ func (r *pwRequest) deploy(ctx *pulumi.Context) error {
192203
}
193204
gateway := subnetInfo.Gateway
194205
localArgs := *glRunnerArgs
206+
localGHScript := ghRunnerScript
195207
piUserDataInput = authToken.ApplyT(func(token string) (*string, error) {
196208
localArgs.AuthToken = token
197209
glSnippet, err := integrations.GetIntegrationSnippetAsCloudInitWritableFile(&localArgs, defaultUser)
@@ -202,7 +214,7 @@ func (r *pwRequest) deploy(ctx *pulumi.Context) error {
202214
if hasOtel {
203215
otelArgs = r.otelArgs(true)
204216
}
205-
ud, err := piUserData(gateway, otelArgs, *glSnippet)
217+
ud, err := piUserData(gateway, otelArgs, *glSnippet, localGHScript)
206218
if err != nil {
207219
return nil, err
208220
}
@@ -213,7 +225,7 @@ func (r *pwRequest) deploy(ctx *pulumi.Context) error {
213225
if hasOtel {
214226
otelArgs = r.otelArgs(false)
215227
}
216-
ud, err := piUserData(subnetInfo.Gateway, otelArgs, "")
228+
ud, err := piUserData(subnetInfo.Gateway, otelArgs, "", ghRunnerScript)
217229
if err != nil {
218230
return fmt.Errorf("failed to render user data: %w", err)
219231
}
@@ -455,7 +467,7 @@ func (r *pwRequest) otelArgs(monitorGitLabRunner bool) *otelcol.OtelcolArgs {
455467

456468
// piUserData renders the cloud-config template and returns it base64-encoded
457469
// for use as PiUserData on a PowerVS instance.
458-
func piUserData(gateway string, otelArgs *otelcol.OtelcolArgs, glRunnerScript string) (string, error) {
470+
func piUserData(gateway string, otelArgs *otelcol.OtelcolArgs, glRunnerScript, ghRunnerScript string) (string, error) {
459471
otelScript := ""
460472
if otelArgs != nil {
461473
s, err := otelcol.GetSnippetAsCloudInitWritableFile(otelArgs)
@@ -466,9 +478,10 @@ func piUserData(gateway string, otelArgs *otelcol.OtelcolArgs, glRunnerScript st
466478
}
467479
script, err := file.Template(
468480
userDataValues{
469-
Gateway: gateway,
470-
OtelColScript: otelScript,
471-
GitLabRunnerScript: glRunnerScript,
481+
Gateway: gateway,
482+
OtelColScript: otelScript,
483+
GitLabRunnerScript: glRunnerScript,
484+
GHActionsRunnerScript: ghRunnerScript,
472485
},
473486
string(CloudConfig))
474487
if err != nil {

0 commit comments

Comments
 (0)