Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Adding ci/cd pipeline using dagger #37

Merged
merged 21 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from 11 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
73 changes: 52 additions & 21 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,33 +1,64 @@
name: Build

on:
# Build only triggers once lint and test workflow successfully completes
workflow_run:
workflows: [Lint]
types:
- completed

jobs:
dagger-build:
dagger-build-satellite:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write
# unless you specify the success on the event,
# this job will also run if the lint workflow was skipped(which is also the case if the condition for the file extension type is false).
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Call Dagger Function to build and publish on Github
uses: dagger/dagger-for-github@v5
with:
version: latest
verb: call
module: github.com/container-registry/harbor-satellite
args: start --name=satellite --source=. --release=./ci --GITHUB-TOKEN=$GITHUB_TOKEN --version=$GITHUB_SHA --REPO_OWNER=$GITHUB_USERNAME --REPO_NAME=harbor-satellite --RELEASE_NAME=satellite
### Uncomment the below line if you wish to see the traces of the workflow on dagger cloud
### register to dagger cloud and get the token
#### https://dagger.cloud/
# cloud-token: ${{ secrets.DAGGER_CLOUD_TOKEN }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_USERNAME: ${{ github.repository_owner }}
GITHUB_SHA: ${{ github.sha }}

build-ground-control:
runs-on: ubuntu-latest
# unless you specify the success on the event,
permissions:
contents: write
packages: write
# unless you specify the success on the event,
# this job will also run if the lint workflow was skipped(which is also the case if the condition for the file extension type is false).
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
-
name: Checkout repository
uses: actions/checkout@v4
-
name: Setup go
uses: actions/setup-go@v4
with:
go-version: '>=1.22'
-
name: Install
run: go get dagger.io/dagger@latest
-
name: Install Dagger CLI
run: cd /usr/local && { curl -L https://dl.dagger.io/dagger/install.sh | sh; cd -; }
-
name: Build with Dagger
run: dagger run go run ci/main.go

- name: Checkout repository
uses: actions/checkout@v4

- name: Call Dagger Function to build and publish on Github
uses: dagger/dagger-for-github@v5
with:
version: latest
verb: call
module: github.com/container-registry/harbor-satellite
args: start --name=ground-control --source=./ground-control --release=./ci --GITHUB-TOKEN=$GITHUB_TOKEN --version=$GITHUB_SHA --REPO_OWNER=$GITHUB_USERNAME --REPO_NAME=harbor-satellite --RELEASE_NAME=ground-control
### Uncomment the below line if you wish to see the traces of the workflow on dagger cloud
### register to dagger cloud and get the token
#### https://dagger.cloud/
# cloud-token: ${{ secrets.DAGGER_CLOUD_TOKEN }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_USERNAME: ${{ github.repository_owner }}
GITHUB_SHA: ${{ github.sha }}
4 changes: 4 additions & 0 deletions ci/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/dagger.gen.go linguist-generated
/internal/dagger/** linguist-generated
/internal/querybuilder/** linguist-generated
/internal/telemetry/** linguist-generated
4 changes: 4 additions & 0 deletions ci/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/dagger.gen.go
/internal/dagger
/internal/querybuilder
/internal/telemetry
64 changes: 64 additions & 0 deletions ci/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Harbor Satellite CI/CD Pipeline

This repository uses [Dagger](https://docs.dagger.io/) for testing, building, and releasing Harbor Satellite.

## Setting Up Dagger for Harbor Satellite

Follow the steps below to set up Dagger:

### 1. Install Dagger CLI

Choose your operating system and install the Dagger CLI:

- **macOS:**
```sh
brew install dagger/tap/dagger
- **Windows:**
```sh
Invoke-WebRequest -UseBasicParsing -Uri https://dl.dagger.io/dagger/install.ps1 | Invoke-Expression; Install-Dagger
- **Linux:**
```sh
curl -L https://dl.dagger.io/dagger/install.sh | BIN_DIR=$HOME/.local/bin sh

### 2. Verify Installation
Run the following command to verify the Dagger installation:
- ```sh
dagger --version
If you encounter any errors, refer to the [detailed installation guide](https://docs.dagger.io/install).

### 3. Generate Go Code
Once the Dagger CLI is installed, navigate to the root folder of harbor-satellite and run:

- ```sh
dagger develop

This command will generate Go code in the ./ci folder.

### 4. Folder Structure
After running dagger develop, your ./ci folder should contain the following structure:
- ```sh
ci/
├── dagger.gen.go
├── ground_control.go
├── internal
│ ├── dagger
│ ├── querybuilder
│ └── telemetry
├── satellite.go
├── README.md
├── release.sh
└── utils.go
If you encounter any issues during this process, consult the [Dagger Quickstart Guide](https://docs.dagger.io/quickstart/daggerize) for more detailed instructions.

## Running Dagger Functions
To view available functions, run:
- ```sh
dagger functions
To run a particular function, run:
- ```sh
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
dagger call <function_name> --args
- #### Example: Building Satellite Binaries
To build the satellite binaries, use the following command:
- ```sh
dagger call build --source=. --name=satellite
This would spin up a container and install required dependencies and build various architecture binaries
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
51 changes: 51 additions & 0 deletions ci/ground_control.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package main

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

"container-registry.com/harbor-satellite/ci/internal/dagger"
)

func (m *HarborSatellite) StartGroundControlCI(ctx context.Context, source *dagger.Directory, release *dagger.Directory, GITHUB_TOKEN, VERSION, REPO_OWNER, REPO_NAME, RELEASE_NAME, name string) error {
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
// Build Ground Control
slog.Info("Building Ground Control")
outputDir := m.Build(ctx, source, name)

release_output, err := m.Release(ctx, outputDir, release, GITHUB_TOKEN, VERSION, REPO_OWNER, REPO_NAME, RELEASE_NAME, name)
if err != nil {
slog.Error("Failed to release Ground Control")
slog.Error(err.Error())
slog.Error((fmt.Sprintf("Release Directory: %s", release_output)))
return err
}
return nil
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
}

func (m *HarborSatellite) ExecuteTestsForGroundControl(ctx context.Context, source *dagger.Directory) (string, error) {
goContainer := dag.Container().
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
From(DEFAULT_GO)

containerWithDocker, err := m.Attach(ctx, goContainer, "24.0")
if err != nil {
return "", err
}
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
dockerHost, err := containerWithDocker.EnvVariable(ctx, "DOCKER_HOST")
if err != nil {
return "", err
}
fmt.Printf("Docker Host: %s\n", dockerHost)

goContainer = containerWithDocker.
WithMountedDirectory("/app", source).
WithWorkdir("/app").
WithExec([]string{"go", "test", "./..."})

output, err := goContainer.Stdout(ctx)
if err != nil {
return output, err
}
fmt.Print(output)
return output, nil
}
109 changes: 93 additions & 16 deletions ci/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,108 @@ package main

import (
"context"
"fmt"
"log/slog"
"os"

"dagger.io/dagger"
"container-registry.com/harbor-satellite/ci/internal/dagger"
)

func main() {
ctx := context.Background()
const (
DEFAULT_GO = "golang:1.22"
PROJ_MOUNT = "/app"
OUT_DIR = "/binaries"
DOCKER_PORT =- 2375
)

// initialize Dagger client
client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr))
if err != nil {
panic(err)
type HarborSatellite struct{}

func (m *HarborSatellite) Start(ctx context.Context, name string, source *dagger.Directory, release *dagger.Directory, GITHUB_TOKEN, VERSION, REPO_OWNER, REPO_NAME, RELEASE_NAME string) {

if name == "" {
slog.Error("Please provide the app name (satellite or ground-control) as an argument")
os.Exit(1)
}
defer client.Close()

// use a golang:1.19 container
// get version
// execute
golang := client.Container().From("golang:1.21").WithExec([]string{"go", "version"})
switch name {
case "satellite":
slog.Info("Starting satellite CI")
err := m.StartSatelliteCi(ctx, source, release, GITHUB_TOKEN, VERSION, REPO_OWNER, REPO_NAME, RELEASE_NAME, name)
if err != nil {
slog.Error("Failed to start satellite CI")
os.Exit(1)
}
case "ground-control":
slog.Info("Starting ground-control CI")
err := m.StartGroundControlCI(ctx, source, release, GITHUB_TOKEN, VERSION, REPO_OWNER, REPO_NAME, RELEASE_NAME, name)
if err != nil {
slog.Error("Failed to complete ground-control CI")
os.Exit(1)
}
default:
slog.Error("Invalid app name. Please provide either 'satellite' or 'ground-control'")
os.Exit(1)
}
}
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved

func (m *HarborSatellite) Build(ctx context.Context, source *dagger.Directory, name string) *dagger.Directory {
return m.build(source, name)
}
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved

func (m *HarborSatellite) Release(ctx context.Context, directory *dagger.Directory, release *dagger.Directory, GITHUB_TOKEN, VERSION, REPO_OWNER, REPO_NAME, RELEASE_NAME, name string) (string, error) {

version, err := golang.Stdout(ctx)
releaseContainer := dag.Container().
From("alpine:latest").
WithDirectory(".", directory).
WithDirectory(".", release).
WithExec([]string{"apk", "add", "--no-cache", "bash", "curl"}).
WithEnvVariable("GITHUB_API_TOKEN", GITHUB_TOKEN).
WithEnvVariable("VERSION", fmt.Sprintf("%s-%s", name, VERSION)).
WithEnvVariable("REPO_OWNER", REPO_OWNER).
WithEnvVariable("REPO_NAME", REPO_NAME).
WithEnvVariable("RELEASE_NAME", RELEASE_NAME).
WithEnvVariable("OUT_DIR", OUT_DIR).
WithExec([]string{"chmod", "+x", "release.sh"}).
WithExec([]string{"ls", "-lR", "."}).
WithExec([]string{"bash", "-c", "./release.sh"})
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
output, err := releaseContainer.Stdout(ctx)
if err != nil {
panic(err)
return output, err
}
// print output
slog.Info("Hello from Dagger!", "version", version)

// Return the updated release directory
return output, nil
}

func (m *HarborSatellite) build(source *dagger.Directory, name string) *dagger.Directory {
fmt.Print("Building Satellite\n")
gooses := []string{"linux", "darwin"}
goarches := []string{"amd64", "arm64"}
binaryName := name // base name for the binary

// create empty directory to put build artifacts
outputs := dag.Directory()

golang := dag.Container().
From(DEFAULT_GO).
WithDirectory(PROJ_MOUNT, source).
WithWorkdir(PROJ_MOUNT)
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
for _, goos := range gooses {
for _, goarch := range goarches {
// create the full binary name with OS and architecture
outputBinary := fmt.Sprintf("%s/%s-%s-%s", OUT_DIR, binaryName, goos, goarch)

// build artifact with specified binary name
build := golang.
WithEnvVariable("GOOS", goos).
WithEnvVariable("GOARCH", goarch).
WithExec([]string{"go", "build", "-o", outputBinary})

// add build to outputs
outputs = outputs.WithDirectory(OUT_DIR, build.Directory(OUT_DIR))
}
}

// return build directory
return outputs
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
}
Loading