diff --git a/src/build.v b/src/build.v index 6b3007f..f303635 100644 --- a/src/build.v +++ b/src/build.v @@ -1,8 +1,66 @@ module main import docker +import encoding.base64 +import rand + +const container_build_dir = '/build' + +struct GitRepo { + url string [required] + branch string [required] +} fn build() { - println(docker.pull('nginx', 'latest') or { panic('yeetus') }) + // println(docker.pull('nginx', 'latest') or { panic('yeetus') }) // println(docker.containers() or { panic('heet') }) + repos := [ + GitRepo{'https://git.rustybever.be/Chewing_Bever/st', 'master'} + GitRepo{'https://aur.archlinux.org/libxft-bgra.git', 'master'} + ] + mut uuids := []string{} + + mut commands := [ + // Update repos & install required packages + 'pacman -Syu --needed --noconfirm base-devel git' + // Add a non-root user to run makepkg + 'groupadd -g 1000 builder' + 'useradd -mg builder builder' + // Make sure they can use sudo without a password + "echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers" + // Create the directory for the builds & make it writeable for the + // build user + 'mkdir /build' + 'chown -R builder:builder /build' + // "su builder -c 'git clone https://git.rustybever.be/Chewing_Bever/st /build/st'" + // 'su builder -c \'cd /build/st && makepkg -s --noconfirm --needed && for pkg in \$(ls -1 *.pkg*); do curl -XPOST -T "\${pkg}" -H "X-API-KEY: \$API_KEY" https://arch.r8r.be/publish; done\'' + ] + + for repo in repos { + mut uuid := rand.uuid_v4() + + // Just to be sure we don't have any collisions + for uuids.contains(uuid) { + uuid = rand.uuid_v4() + } + + uuids << uuid + + commands << "su builder -c 'git clone --single-branch --depth 1 --branch $repo.branch $repo.url /build/$uuid'" + commands << 'su builder -c \'cd /build/$uuid && makepkg -s --noconfirm --needed && for pkg in \$(ls -1 *.pkg*); do curl -XPOST -T "\${pkg}" -H "X-API-KEY: \$API_KEY" https://arch.r8r.be/publish; done\'' + } + println(commands) + + // We convert the list of commands into a base64 string + cmds_str := base64.encode_str(commands.join('\n')) + + c := docker.NewContainer{ + image: 'archlinux:latest' + env: ['BUILD_SCRIPT=$cmds_str'] + entrypoint: ['/bin/sh', '-c'] + cmd: ['echo \$BUILD_SCRIPT | base64 -d | /bin/sh -e'] + } + + id := docker.create_container(c) or { panic('aaaahh') } + print(docker.start_container(id) or { panic('yikes') }) } diff --git a/src/docker/containers.v b/src/docker/containers.v index 8ac6a66..f7eb8c7 100644 --- a/src/docker/containers.v +++ b/src/docker/containers.v @@ -9,7 +9,35 @@ struct Container { } pub fn containers() ?[]Container { - res := get(urllib.parse('/containers/json') ?) ? + res := request('GET', urllib.parse('/containers/json') ?) ? return json.decode([]Container, res.text) or {} } + +pub struct NewContainer { + image string [json: Image] + entrypoint []string [json: Entrypoint] + cmd []string [json: Cmd] + env []string [json: Env] +} + +struct CreatedContainer { + id string [json: Id] +} + +pub fn create_container(c &NewContainer) ?string { + res := request_with_json('POST', urllib.parse('/containers/create') ?, c) ? + + if res.status_code != 201 { + return error('Failed to create container.') + } + + return json.decode(CreatedContainer, res.text) ?.id +} + +pub fn start_container(id string) ?bool { + res := request('POST', urllib.parse('/containers/$id/start') ?) ? + println(res) + + return res.status_code == 204 +} diff --git a/src/docker/docker.v b/src/docker/docker.v index 8873a9c..9eda41f 100644 --- a/src/docker/docker.v +++ b/src/docker/docker.v @@ -64,8 +64,8 @@ fn send(req &string) ?http.Response { return http.parse_response(res.bytestr()) } -fn request_with_body(method string, url urllib.URL, body &string) ?http.Response { - req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\nContent-Length: $body.len\n$body\n' +fn request_with_body(method string, url urllib.URL, content_type string, body string) ?http.Response { + req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\nContent-Type: ${content_type}\nContent-Length: $body.len\n\n$body\n\n' return send(req) } @@ -76,19 +76,10 @@ fn request(method string, url urllib.URL) ?http.Response { return send(req) } -pub fn request_with_json(method string, url urllib.URL, data T) ?http.Response { +pub fn request_with_json(method string, url urllib.URL, data &T) ?http.Response { body := json.encode(data) - return request_with_body(method, url, body) -} - -fn get(url urllib.URL) ?http.Response { - return request('GET', url) -} - -struct ImagePull { - from_image string [json: fromImage] - tag string + return request_with_body(method, url, 'application/json', body) } pub fn pull(image string, tag string) ?http.Response {