package main import ( "context" "encoding/xml" "fmt" "os" "path" "time" "dagger.io/dagger" ) type info struct { Version string `xml:"version"` } func main() { ctx := context.Background() // initialize Dagger client client, err := dagger.Connect(ctx, dagger.WithLogOutput(os.Stderr)) if err != nil { panic(err) } defer client.Close() keySecret := loadSecret(client, "scimserviceprovider.key") certSecret := loadSecret(client, "scimserviceprovider.crt") s3Secret := client.SetSecret("s3", fmt.Sprintf("https://%s:%s@hot-objects.liiib.re", os.Getenv("S3_ACCESSKEY"), os.Getenv("S3_SECRETKEY"))) ncSecret := client.SetSecret("nc", os.Getenv("NC_STORE_TOKEN")) i := loadInfo() archiveName := fmt.Sprintf("scimserviceprovider-v%s.tar.gz", i.Version) fmt.Println("cc", i.Version) // execute vendor := client.Container().From("docker.io/composer:2.6"). WithFile("composer.json", client.Host().File("composer.json")). WithFile("composer.lock", client.Host().File("composer.lock")). WithExec([]string{"composer", "i", "--no-dev", "--ignore-platform-reqs"}). WithExec([]string{"rm", "-rf", "vendor/audriga/scim-server-php/.git"}). Directory("vendor") output := client.Container().From("docker.io/nextcloud:28"). WithWorkdir("/scimserviceprovider"). WithDirectory("vendor", vendor). WithDirectory(".", client.Host().Directory(".", dagger.HostDirectoryOpts{ Include: []string{"appinfo", "lib", "LICENSE"}, })). WithMountedSecret("/scimserviceprovider.crt", certSecret). WithMountedSecret("/scimserviceprovider.key", keySecret). WithExec([]string{"php", "/usr/src/nextcloud/occ", "integrity:sign-app", "--path=/scimserviceprovider", "--privateKey=/scimserviceprovider.key", "--certificate=/scimserviceprovider.crt"}). WithExec([]string{"mkdir", "/output"}). WithExec([]string{"tar", "czf", path.Join("/output", archiveName), "/scimserviceprovider"}). WithExec([]string{"bash", "-c", "openssl dgst -sha512 -sign /scimserviceprovider.key " + path.Join("/output", archiveName) + " | openssl base64 > " + path.Join("/output", archiveName+".sign")}). Directory("/output") _, err = client.Container().From("docker.io/minio/mc"). WithSecretVariable("MC_HOST_repo", s3Secret). WithDirectory("/output", output). WithExec([]string{"mc", "cp", "-r", "/output/", "repo/artifacts/"}). Sync(ctx) if err != nil { panic(err) } _, err = client.Container().From("docker.io/alpine"). WithExec([]string{"apk", "add", "--no-cache", "curl"}). WithWorkdir("/output"). WithDirectory("/output", output). WithEnvVariable("ARCHIVE_NAME", archiveName). WithSecretVariable("TOKEN", ncSecret). WithEnvVariable("CACHEBUSTER", time.Now().String()). WithExec([]string{"sh", "-c", `printf '{"download":"https://hot-objects.liiib.re/artifacts/%s", "signature": "%s"}' "$ARCHIVE_NAME" "$(cat ${ARCHIVE_NAME}.sign)" | curl --fail-with-body -s -X POST https://apps.nextcloud.com/api/v1/apps/releases -H "Authorization: Token ${TOKEN}" -H "Content-Type: application/json" -d @-`}). Sync(ctx) if err != nil { panic(err) } } func loadSecret(client *dagger.Client, name string) *dagger.Secret { home, err := os.UserHomeDir() if err != nil { panic(err) } data, err := os.ReadFile(path.Join(home, ".nextcloud/certificates/", name)) if err != nil { panic(err) } return client.SetSecret(name, string(data)) } func loadInfo() info { data, err := os.ReadFile("appinfo/info.xml") if err != nil { panic(err) } i := info{} err = xml.Unmarshal(data, &i) if err != nil { panic(err) } return i }