Update Dagger pipeline and documentation for Gitea release upload and .env handling
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -38,4 +38,7 @@ Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
# Dagger cache
|
||||
.dagger/
|
||||
.dagger/
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
20
README.md
20
README.md
@@ -218,19 +218,35 @@ The pipeline is defined in [`ci/dagger.go`](./ci/dagger.go). It outputs binaries
|
||||
|
||||
### Usage
|
||||
|
||||
1. Install the Dagger Go SDK:
|
||||
1. Install the Dagger Go SDK and dependencies:
|
||||
```sh
|
||||
go install dagger.io/dagger@latest
|
||||
go get github.com/joho/godotenv
|
||||
go mod tidy
|
||||
```
|
||||
2. Run the pipeline:
|
||||
2. Build for all platforms:
|
||||
```sh
|
||||
go run ci/dagger.go
|
||||
```
|
||||
3. (Optional) Upload binaries to a Gitea release:
|
||||
- Create a `.env` file in the project root with:
|
||||
```
|
||||
GITEA_TOKEN=your_token
|
||||
GITEA_URL=https://your.gitea.server
|
||||
GITEA_OWNER=youruser
|
||||
GITEA_REPO=yourrepo
|
||||
```
|
||||
- Run:
|
||||
```sh
|
||||
go run ci/dagger.go --release v1.0.0
|
||||
```
|
||||
- This will create (if needed) and upload all binaries to the specified release tag on your Gitea instance.
|
||||
- **The pipeline will also create and push a local git tag for the release if it does not already exist.**
|
||||
|
||||
### Troubleshooting Dagger
|
||||
- If you see `could not import dagger.io/dagger`, make sure you have installed the Dagger Go SDK and run `go mod tidy`.
|
||||
- The pipeline requires Docker or a compatible container runtime.
|
||||
- For Gitea upload, ensure your `.env` file is present and correct.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
4
ci/.env.example
Normal file
4
ci/.env.example
Normal file
@@ -0,0 +1,4 @@
|
||||
GITEA_TOKEN=your_token
|
||||
GITEA_URL=https://your.gitea.server
|
||||
GITEA_OWNER=youruser
|
||||
GITEA_REPO=yourrepo
|
||||
164
ci/dagger.go
164
ci/dagger.go
@@ -1,16 +1,35 @@
|
||||
// Dagger pipeline for multi-platform builds.
|
||||
// Requires: go install dagger.io/dagger@latest && go mod tidy
|
||||
// Usage:
|
||||
//
|
||||
// go run ci/dagger.go [--release v1.0.0]
|
||||
//
|
||||
// If --release is provided, uploads all built binaries in dist/ to the specified Gitea release.
|
||||
// Requires .env file with GITEA_TOKEN, GITEA_URL, GITEA_OWNER, GITEA_REPO.
|
||||
// Requires: go install dagger.io/dagger@latest && go get github.com/joho/godotenv && go mod tidy
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"dagger.io/dagger"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
releaseTag := flag.String("release", "", "(optional) Release tag to upload binaries to Gitea")
|
||||
flag.Parse()
|
||||
|
||||
ctx := context.Background()
|
||||
client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stdout))
|
||||
if err != nil {
|
||||
@@ -30,6 +49,8 @@ func main() {
|
||||
|
||||
src := client.Host().Directory(".")
|
||||
|
||||
var builtBinaries []string
|
||||
|
||||
for _, p := range platforms {
|
||||
binName := fmt.Sprintf("valhallir-deconvolver-%s-%s", p.OS, p.Arch)
|
||||
if p.OS == "windows" {
|
||||
@@ -50,5 +71,146 @@ func main() {
|
||||
panic(fmt.Sprintf("export failed for %s/%s: %v", p.OS, p.Arch, err))
|
||||
}
|
||||
fmt.Printf("Built and exported %s\n", outPath)
|
||||
builtBinaries = append(builtBinaries, outPath)
|
||||
}
|
||||
|
||||
if *releaseTag != "" {
|
||||
fmt.Printf("\nUploading binaries to Gitea release: %s\n", *releaseTag)
|
||||
// Load .env
|
||||
err := godotenv.Load("ci/.env")
|
||||
if err != nil {
|
||||
panic("Error loading .env file: " + err.Error())
|
||||
}
|
||||
giteaToken := os.Getenv("GITEA_TOKEN")
|
||||
giteaURL := os.Getenv("GITEA_URL")
|
||||
giteaOwner := os.Getenv("GITEA_OWNER")
|
||||
giteaRepo := os.Getenv("GITEA_REPO")
|
||||
if giteaToken == "" || giteaURL == "" || giteaOwner == "" || giteaRepo == "" {
|
||||
panic("GITEA_TOKEN, GITEA_URL, GITEA_OWNER, GITEA_REPO must be set in .env")
|
||||
}
|
||||
|
||||
// 1. Get or create the release
|
||||
releaseID, err := getOrCreateRelease(giteaURL, giteaOwner, giteaRepo, *releaseTag, giteaToken)
|
||||
if err != nil {
|
||||
panic("Failed to get or create release: " + err.Error())
|
||||
}
|
||||
|
||||
// 2. Upload each binary as an asset
|
||||
for _, bin := range builtBinaries {
|
||||
fmt.Printf("Uploading %s...\n", bin)
|
||||
err := uploadAsset(giteaURL, giteaOwner, giteaRepo, releaseID, bin, giteaToken)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to upload %s: %v", bin, err))
|
||||
}
|
||||
fmt.Printf("Uploaded %s\n", bin)
|
||||
}
|
||||
fmt.Println("All binaries uploaded to Gitea release.")
|
||||
|
||||
// 3. Tag the release locally and push the tag
|
||||
if err := tagAndPush(*releaseTag); err != nil {
|
||||
panic("Failed to tag and push: " + err.Error())
|
||||
}
|
||||
fmt.Printf("Tagged and pushed %s\n", *releaseTag)
|
||||
}
|
||||
}
|
||||
|
||||
func getOrCreateRelease(url, owner, repo, tag, token string) (int, error) {
|
||||
// Try to get the release by tag
|
||||
api := fmt.Sprintf("%s/api/v1/repos/%s/%s/releases/tags/%s", strings.TrimRight(url, "/"), owner, repo, tag)
|
||||
req, _ := http.NewRequest("GET", api, nil)
|
||||
req.Header.Set("Authorization", "token "+token)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == 200 {
|
||||
// Parse JSON to get ID
|
||||
type releaseResp struct{ ID int }
|
||||
var r releaseResp
|
||||
io.ReadAll(resp.Body) // ignore body for now, parse below
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
dec.Decode(&r)
|
||||
return r.ID, nil
|
||||
}
|
||||
// If not found, create it
|
||||
if resp.StatusCode == 404 {
|
||||
api = fmt.Sprintf("%s/api/v1/repos/%s/%s/releases", strings.TrimRight(url, "/"), owner, repo)
|
||||
body := strings.NewReader(fmt.Sprintf(`{"tag_name":"%s","name":"%s"}`, tag, tag))
|
||||
req, _ = http.NewRequest("POST", api, body)
|
||||
req.Header.Set("Authorization", "token "+token)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
resp, err = http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == 201 {
|
||||
type releaseResp struct{ ID int }
|
||||
var r releaseResp
|
||||
dec := json.NewDecoder(resp.Body)
|
||||
dec.Decode(&r)
|
||||
return r.ID, nil
|
||||
}
|
||||
return 0, fmt.Errorf("failed to create release: %s", resp.Status)
|
||||
}
|
||||
return 0, fmt.Errorf("failed to get release: %s", resp.Status)
|
||||
}
|
||||
|
||||
func uploadAsset(url, owner, repo string, releaseID int, filePath, token string) error {
|
||||
api := fmt.Sprintf("%s/api/v1/repos/%s/%s/releases/%d/assets?name=%s", strings.TrimRight(url, "/"), owner, repo, releaseID, filepath.Base(filePath))
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var b bytes.Buffer
|
||||
w := multipart.NewWriter(&b)
|
||||
f, err := w.CreateFormFile("attachment", filepath.Base(filePath))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(f, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Close()
|
||||
|
||||
req, _ := http.NewRequest("POST", api, &b)
|
||||
req.Header.Set("Authorization", "token "+token)
|
||||
req.Header.Set("Content-Type", w.FormDataContentType())
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 201 {
|
||||
return fmt.Errorf("upload failed: %s", resp.Status)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func tagAndPush(tag string) error {
|
||||
// Check if tag exists
|
||||
cmd := exec.Command("git", "tag", "--list", tag)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if strings.TrimSpace(string(out)) == tag {
|
||||
// Tag already exists
|
||||
return nil
|
||||
}
|
||||
// Create tag
|
||||
cmd = exec.Command("git", "tag", tag)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
// Push tag
|
||||
cmd = exec.Command("git", "push", "origin", tag)
|
||||
if err := cmd.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@@ -6,6 +6,7 @@ require (
|
||||
dagger.io/dagger v0.18.12
|
||||
github.com/go-audio/audio v1.0.0
|
||||
github.com/go-audio/wav v1.1.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/mjibson/go-dsp v0.0.0-20180508042940-11479a337f12
|
||||
github.com/urfave/cli/v2 v2.27.7
|
||||
gonum.org/v1/gonum v0.13.0
|
||||
|
||||
2
go.sum
2
go.sum
@@ -35,6 +35,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mjibson/go-dsp v0.0.0-20180508042940-11479a337f12 h1:dd7vnTDfjtwCETZDrRe+GPYNLA1jBtbZeyfyE8eZCyk=
|
||||
|
||||
Reference in New Issue
Block a user