Skip to content
Snippets Groups Projects
server.go 3.61 KiB
Newer Older
Sven's avatar
Sven committed
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"time"

	"github.com/ifo/gozulipbot"
	"github.com/xanzy/go-gitlab"

Sven's avatar
Sven committed
	"gitli.stratum0.org/heyalter/bots"
)
Sven's avatar
Sven committed

type Config struct {
Sven's avatar
Sven committed
	bots.ZuliprcAPISection                `ini:"api"`
Sven's avatar
Sven committed
	GitLabWebhookToken string
}


var isoURLRegexp *regexp.Regexp = regexp.MustCompile(`data-external-link="false"\s+data-link="/heyalter/heyalter-ubuntu-iso/-/jobs/\d+/artifacts/file/([^"]*\.iso)"`)

func HandleWebhook(w http.ResponseWriter, req *http.Request, webhookToken string, zlbot *gozulipbot.Bot) {
	if req.Header.Get("X-Gitlab-Token") != webhookToken {
		w.WriteHeader(http.StatusUnauthorized)
		return
	}

	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	ev, err := gitlab.ParseWebhook(gitlab.EventTypePipeline, data)
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	event := ev.(*gitlab.PipelineEvent)

	if event.ObjectAttributes.Status != "success" {
		// Too early, not important
Sven's avatar
Sven committed
		w.WriteHeader(http.StatusAccepted)
Sven's avatar
Sven committed
		return
	}
	if event.ObjectAttributes.Ref != event.Project.DefaultBranch {
		// Not the default branch => not a release => ignoring
Sven's avatar
Sven committed
		w.WriteHeader(http.StatusNoContent)
Sven's avatar
Sven committed
		return
	}

	// Find the ISO...
	for _, build := range event.Builds {
		if build.ArtifactsFile.Filename == "" {
			continue
		}

		// The last artifacts part may change if the artifacts are stored in another dir
		resp, err := http.Get(fmt.Sprintf("https://gitli.stratum0.org/heyalter/heyalter-ubuntu-iso/-/jobs/%d/artifacts/browse/artifacts/", build.ID))
		if err != nil {
			log.Println("Couldn't get artifacts for job", build.ID, ":", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		artifactshtml, err := ioutil.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			log.Println("Couldn't read artifacts for job", build.ID, ":", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		match := isoURLRegexp.FindStringSubmatch(string(artifactshtml))
		if match == nil || len(match) < 2 {
			log.Println("Couldn't find iso in artifacts for job", build.ID, ":", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
		}

		// Got it all...
		isoURL := fmt.Sprintf("https://gitli.stratum0.org/heyalter/heyalter-ubuntu-iso/-/jobs/%d/artifacts/raw/%s", build.ID, match[1])
		zipURL := fmt.Sprintf("https://gitli.stratum0.org/heyalter/heyalter-ubuntu-iso/-/jobs/%d/artifacts/download", build.ID)
		changelogURL := fmt.Sprintf("https://gitli.stratum0.org/heyalter/heyalter-ubuntu-iso/-/blob/%s/changelog.md", event.ObjectAttributes.SHA)

		prefix := "Soeben wurde ein neues ISO-Image gebaut!\nDownload:"
		if now := time.Now(); now.Day() == 1 && now.Month() == time.April {
			prefix = "Nur heute: ISO-Image inkl. Versand via TCP für nur 0€ inkl. MwSt.!\nKaufen sie noch heute ihr ISO-Image!\nKlicken sie hier:"
		}

		if _, err := zlbot.Message(gozulipbot.Message{
			Stream:  "Hilfe/Technik",
			Topic:   "ISO Releases",
			Content: fmt.Sprintf("%s [ISO](%s) ([Zip](%s), [Changelog](%s))", prefix, isoURL, zipURL, changelogURL),
		}); err != nil {
			log.Println("Couldn't send chat message for job", build.ID, ":", err)
			w.WriteHeader(http.StatusInternalServerError)
			return
Sven's avatar
Sven committed
		}	}
Sven's avatar
Sven committed
}

func main() {
Sven's avatar
Sven committed
	var cfg Config
	zlbot, err := bots.InitZulip(&cfg)
Sven's avatar
Sven committed
	if err != nil {
Sven's avatar
Sven committed
		fmt.Println("Couldn't load config because of the error", err)
Sven's avatar
Sven committed
	listen := "localhost:8080"
		if len(os.Args) > 2 {
			listen = os.Args[2]
		}
Sven's avatar
Sven committed

Sven's avatar
Sven committed
	http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { HandleWebhook(w, req, cfg.GitLabWebhookToken, zlbot) })
Sven's avatar
Sven committed
	log.Fatal(http.ListenAndServe(listen, nil))
}