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 17 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: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ go.work
dist/

# Remove DS_Store
.DS_Store
.DS_Store
zot/cache.db
secrets.txt
59 changes: 59 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com

# The lines below are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/need to use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj

version: 2
project_name: harbor-satellite

git:
ignore_tags:
- "*-ground-control"
builds:
- main: "./main.go"
binary: "{{ .Env.APP_NAME }}"
env:
- CGO_ENABLED=0
ldflags:
- -w -s -X github.com/Mehul-Kumar-27/harbor-satellite/internal/version.GitCommit={{.FullCommit}}
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
goos:
- linux
- darwin
goarch:
- amd64
- arm64
ignore:
- goos: windows
goarch: arm
- goos: windows
goarch: arm64
mod_timestamp: "{{ .CommitTimestamp }}"


release:
name_template: "{{ .Env.APP_NAME }}_{{ .ShortCommit }}"

archives:
- format: tar.gz
# this name template makes the OS and Arch compatible with the results of `uname`.
name_template: >-
{{ .Env.APP_NAME }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end }}
# use zip for windows archives
format_overrides:
- goos: windows
format: zip

changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
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
36 changes: 36 additions & 0 deletions ci/ground_control.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"context"
"fmt"

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

// Would execute the tests for the ground control. Source should be the path to the path to main.go file.
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
}
88 changes: 71 additions & 17 deletions ci/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,85 @@ 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"
DOCKER_PORT = 2375
GORELEASER_VERSION = "v2.1.0"
GROUND_CONTROL_PATH = "./ground-control"
SATELLITE_PATH = "."
)

type HarborSatellite struct{}

// Build function would start the build process for the name provided. Source should be the path to the main.go file.
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

// Release function would release the build to the github with the tags provided. Directory should be "." for both the satellite and the ground control.
func (m *HarborSatellite) Release(ctx context.Context, directory *dagger.Directory, token, name string) (string, error) {
var path_to_main string

if name == "satellite" {
path_to_main = ".goreleaser.yaml"
} else {
path_to_main = "ground-control/.goreleaser.yaml"
}
release_output, err := dag.Container().
From(fmt.Sprintf("goreleaser/goreleaser:%s", GORELEASER_VERSION)).
WithMountedDirectory(PROJ_MOUNT, directory).
WithWorkdir(PROJ_MOUNT).
WithEnvVariable("GITHUB_TOKEN", token).
WithEnvVariable("PATH_TO_MAIN", path_to_main).
WithEnvVariable("APP_NAME", name).
WithExec([]string{"goreleaser", "release", "-f", path_to_main, "--clean"}).
Stderr(ctx)

// initialize Dagger client
client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr))
if err != nil {
panic(err)
slog.Error("Failed to release Ground Control: ", err, ".")
slog.Error("Release Output:", release_output, ".")
return release_output, err
}
defer client.Close()

// use a golang:1.19 container
// get version
// execute
golang := client.Container().From("golang:1.21").WithExec([]string{"go", "version"})
return release_output, nil
}

version, err := golang.Stdout(ctx)
if err != nil {
panic(err)
func (m *HarborSatellite) build(source *dagger.Directory, name string) *dagger.Directory {
fmt.Printf("Building %s\n", name)
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", name, 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(name, build.Directory(name))
}
}
// print output
slog.Info("Hello from Dagger!", "version", version)

// return build directory
return outputs
}
Loading