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 19 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
91 changes: 70 additions & 21 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,33 +1,82 @@
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: Build the binary for the satellite
uses: dagger/dagger-for-github@v5
with:
version: latest
verb: call
module: github.com/container-registry/harbor-satellite
args: build --source=. --name=satellite

- name: Release on Github
uses: dagger/dagger-for-github@v5
with:
version: latest
verb: call
module: github.com/container-registry/harbor-satellite
args: release --source=. --name=satellite --token=$GITHUB_TOKEN

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_USERNAME: ${{ github.repository_owner }}
GITHUB_SHA: ${{ github.sha }}
### 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 }}

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: Build the binary for ground control
uses: dagger/dagger-for-github@v5
with:
version: latest
verb: call
module: github.com/container-registry/harbor-satellite
args: build --source=./ground-control --name=ground-control

- name: Release on Github
uses: dagger/dagger-for-github@v5
with:
version: latest
verb: call
module: github.com/container-registry/harbor-satellite
args: release --source=. --name=ground-control --token=$GITHUB_TOKEN

env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_USERNAME: ${{ github.repository_owner }}
GITHUB_SHA: ${{ github.sha }}
### 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 }}
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/container-registry/harbor-satellite/internal/version.GitCommit={{.FullCommit}}
goos:
- linux
- darwin
goarch:
- amd64
- arm64
ignore:
- goos: windows
goarch: arm
- goos: windows
goarch: arm64
mod_timestamp: "{{ .CommitTimestamp }}"


release:
name_template: "{{ .Tag }}"

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
74 changes: 74 additions & 0 deletions ci/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# 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 export --path=./bin
This would spin up a container and install required dependencies and build various architecture binaries and export them to the host on path ./bin for testing on the host.
- #### Example: Releasing to GitHub
To release the project on GitHub, use the following command
- ```sh
dagger call release --directory=. --token=<your_github_token> --name=satellite
The above function would then proceed to release the project on github for the name provided. The above function also takes argument `--release-type` which would tell the release what kind of release it is i.e major, minor or path, The default value is set to be path release
- #### Example: Releasing to GitHub with type of release
To release the project on GitHub, use the following command
- ```sh
dagger call release --directory=. --token=<your_github_token> --name=satellite --release-type=minor
The above function would release the minor version for the project mentioned
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
}
72 changes: 56 additions & 16 deletions ci/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,71 @@ 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)
}

// 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,
// +optional
// +default="patch"
release_type string) (string, error) {

// initialize Dagger client
client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr))
container := dag.Container().
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
From("alpine/git").
WithEnvVariable("GITHUB_TOKEN", token).
WithMountedDirectory(PROJ_MOUNT, directory).
WithWorkdir(PROJ_MOUNT).
WithExec([]string{"git", "config", "--global", "url.https://github.com/.insteadOf", "[email protected]:"}).
WithExec([]string{"git", "fetch", "--tags"})
// Prepare the tags for the release
release_tag, err := m.get_release_tag(ctx, container, directory, name, release_type)
if err != nil {
panic(err)
slog.Error("Failed to prepare for release: ", err, ".")
slog.Error("Tag Release Output:", release_tag, ".")
os.Exit(1)
Mehul-Kumar-27 marked this conversation as resolved.
Show resolved Hide resolved
}
defer client.Close()

// use a golang:1.19 container
// get version
// execute
golang := client.Container().From("golang:1.21").WithExec([]string{"go", "version"})
slog.Info("Tag Release Output:", release_tag, ".")
pathToMain, err := m.getPathToReleaser(name)
if err != nil {
slog.Error("Failed to get path to main: ", err, ".")
os.Exit(1)
}
release_output, err := container.
From(fmt.Sprintf("goreleaser/goreleaser:%s", GORELEASER_VERSION)).
WithMountedDirectory(PROJ_MOUNT, directory).
WithWorkdir(PROJ_MOUNT).
WithEnvVariable("GITHUB_TOKEN", token).
WithEnvVariable("PATH_TO_MAIN", pathToMain).
WithEnvVariable("APP_NAME", name).
WithExec([]string{"git", "tag", release_tag}).
WithExec([]string{"goreleaser", "release", "-f", pathToMain, "--clean"}).
Stderr(ctx)

version, err := golang.Stdout(ctx)
if err != nil {
panic(err)
slog.Error("Failed to release: ", err, ".")
slog.Error("Release Output:", release_output, ".")
os.Exit(1)
}
// print output
slog.Info("Hello from Dagger!", "version", version)

return release_output, nil
}
Loading