mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-28 01:03:10 -06:00
101 lines
2.7 KiB
Go
101 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/codeclysm/extract"
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/client"
|
|
)
|
|
|
|
var (
|
|
flagTempDir = flag.String("tmp", "tmp", "Path to temporary directory to dump tarballs to")
|
|
)
|
|
|
|
func ptr(in string) *string {
|
|
return &in
|
|
}
|
|
|
|
// downloadArchive downloads an arbitrary github archive of the form:
|
|
// https://github.com/matrix-org/dendrite/archive/v0.3.11.tar.gz
|
|
// and re-tarballs it without the top-level directory which contains branch information. It inserts
|
|
// the contents of `dockerfile` as a root file `Dockerfile` in the re-tarballed directory such that
|
|
// you can directly feed the retarballed archive to `ImageBuild` to have it run said dockerfile.
|
|
// Returns the tarball buffer on success.
|
|
func downloadArchive(cli *http.Client, archiveURL string, dockerfile []byte) (*bytes.Buffer, error) {
|
|
tmpDir := *flagTempDir
|
|
resp, err := cli.Get(archiveURL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != 200 {
|
|
return nil, fmt.Errorf("got HTTP %d", resp.StatusCode)
|
|
}
|
|
os.Mkdir(tmpDir, os.ModePerm)
|
|
defer os.RemoveAll(tmpDir)
|
|
// dump the tarball temporarily, stripping the top-level directory
|
|
err = extract.Archive(context.Background(), resp.Body, tmpDir, func(inPath string) string {
|
|
// remove top level
|
|
segments := strings.Split(inPath, "/")
|
|
return strings.Join(segments[1:], "/")
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// add top level Dockerfile
|
|
err = ioutil.WriteFile(path.Join(tmpDir, "Dockerfile"), dockerfile, os.ModePerm)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to inject /Dockerfile: %w", err)
|
|
}
|
|
// now re-tarball it :/
|
|
var tarball bytes.Buffer
|
|
err = compress(*flagTempDir, &tarball)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &tarball, nil
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
httpClient := &http.Client{
|
|
Timeout: 60 * time.Second,
|
|
}
|
|
// pull an archive, this contains a top-level directory which screws with the build context
|
|
// which we need to fix up post download
|
|
u := "https://github.com/matrix-org/dendrite/archive/v0.3.11.tar.gz"
|
|
tarball, err := downloadArchive(httpClient, u, []byte("FROM golang:1.15\nRUN echo 'hello world'"))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fmt.Printf("%s => %d bytes\n", u, tarball.Len())
|
|
|
|
cli, err := client.NewEnvClient()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fmt.Println("building...")
|
|
res, err := cli.ImageBuild(context.Background(), tarball, types.ImageBuildOptions{
|
|
Tags: []string{"dendrite-upgrade"},
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer res.Body.Close()
|
|
body, err := ioutil.ReadAll(res.Body)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
fmt.Println(string(body))
|
|
}
|