Skip to content
This repository was archived by the owner on Apr 15, 2023. It is now read-only.

Commit 37b2bb9

Browse files
authored
Initial import (#1)
1 parent 39aae1d commit 37b2bb9

File tree

7 files changed

+397
-0
lines changed

7 files changed

+397
-0
lines changed

.gitignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Created by .ignore support plugin (hsz.mobi)
2+
### Go template
3+
# Binaries for programs and plugins
4+
*.exe
5+
*.dll
6+
*.so
7+
*.dylib
8+
9+
# Test binary, build with `go test -c`
10+
*.test
11+
12+
# Output of the go coverage tool, specifically when used with LiteIDE
13+
*.out
14+
15+
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
16+
.glide/
17+
18+
# IDE
19+
.idea/

Dockerfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM golang:alpine
2+
3+
RUN apk add --no-cache git
4+
5+
ADD . /go/src/github.com/fankserver/docker-factorio-watchdog
6+
RUN go get github.com/fankserver/docker-factorio-watchdog/... \
7+
&& go install github.com/fankserver/docker-factorio-watchdog
8+
ENTRYPOINT /go/bin/docker-factorio-watchdog

docker-factorio-watchdog.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/blang/semver"
8+
"github.com/robfig/cron"
9+
"github.com/sirupsen/logrus"
10+
)
11+
12+
var latestVersionProceeded map[string]string
13+
14+
func main() {
15+
latestVersionProceeded = map[string]string{}
16+
checkVersion()
17+
c := cron.New()
18+
c.AddFunc("@every 5m", func() { checkVersion() })
19+
c.Run()
20+
}
21+
22+
func checkVersion() {
23+
version, err := GetAvailableVersions()
24+
if err != nil {
25+
logrus.Panic(err)
26+
}
27+
28+
// Get all available versions
29+
versions := semver.Versions{}
30+
for _, version := range version.CoreLinuxHeadless64 {
31+
if version.To == "" {
32+
continue
33+
}
34+
v, err := semver.Make(version.To)
35+
if err != nil {
36+
logrus.Error(err)
37+
continue
38+
}
39+
40+
versions = append(versions, v)
41+
}
42+
semver.Sort(versions)
43+
44+
// Filter only latest version based on minor
45+
var lastVersion semver.Version
46+
firstRun := true
47+
lastVersions := semver.Versions{}
48+
for i, version := range versions {
49+
if firstRun {
50+
lastVersion = version
51+
firstRun = false
52+
}
53+
54+
if lastVersion.Major != version.Major || lastVersion.Minor != version.Minor {
55+
lastVersions = append(lastVersions, lastVersion)
56+
} else if i+1 == len(versions) {
57+
lastVersions = append(lastVersions, version)
58+
}
59+
60+
lastVersion = version
61+
}
62+
63+
// Remove all tags which are published on docker
64+
tags, err := getTags()
65+
for _, tag := range tags {
66+
tagVersion, err := semver.Make(tag.Name)
67+
if err != nil {
68+
continue
69+
}
70+
for i, version := range lastVersions {
71+
if version.String() == tag.Name {
72+
lastVersions = append(lastVersions[:i], lastVersions[i+1:]...)
73+
}
74+
}
75+
76+
key := fmt.Sprintf("%d.%d", tagVersion.Major, tagVersion.Minor)
77+
if val, ok := latestVersionProceeded[key]; ok {
78+
if val == tagVersion.String() {
79+
logrus.Info("Delete ", tagVersion.String(), " from latest proceeded")
80+
delete(latestVersionProceeded, key)
81+
}
82+
}
83+
}
84+
85+
for _, version := range lastVersions {
86+
if version.Major == 0 && version.Minor < 13 {
87+
continue
88+
}
89+
key := fmt.Sprintf("%d.%d", version.Major, version.Minor)
90+
91+
logrus.Info(latestVersionProceeded)
92+
if val, ok := latestVersionProceeded[key]; ok {
93+
logrus.Info("OK ", val)
94+
if val == version.String() {
95+
logrus.Info("Version exists in cache SKIP")
96+
continue
97+
}
98+
}
99+
100+
updateVersion(version)
101+
}
102+
}
103+
104+
func updateVersion(version semver.Version) {
105+
logrus.Info("Start ", version.String())
106+
latestVersionProceeded[fmt.Sprintf("%d.%d", version.Major, version.Minor)] = version.String()
107+
pathRepo := fmt.Sprintf("/tmp/factorio-%s-repo", version)
108+
109+
err := gitCloneRepo(pathRepo)
110+
if err != nil {
111+
logrus.Panic(err)
112+
}
113+
defer os.RemoveAll(pathRepo)
114+
logrus.Info("Cloned repo")
115+
116+
err = gitCheckoutBranch(pathRepo, "update-"+version.String())
117+
if err != nil {
118+
logrus.Panic(err)
119+
}
120+
logrus.Info("Checkout branch ", version)
121+
122+
checksum, err := factorioGetChecksum(fmt.Sprintf("https://www.factorio.com/get-download/%s/headless/linux64", version))
123+
if err != nil {
124+
logrus.Panic(err)
125+
}
126+
logrus.Info("Got checksum ", checksum)
127+
128+
err = editDockerfile(pathRepo, version, checksum)
129+
if err != nil {
130+
logrus.Panic(err)
131+
}
132+
logrus.Info("Edited Dockerfile")
133+
err = editReadme(pathRepo, version)
134+
if err != nil {
135+
logrus.Panic(err)
136+
}
137+
logrus.Info("Edited README")
138+
139+
err = gitCreateCommit(pathRepo, "update")
140+
if err != nil {
141+
logrus.Panic(err)
142+
}
143+
logrus.Info("Committed")
144+
145+
err = gitPushBranch(pathRepo, "update-"+version.String())
146+
if err != nil {
147+
logrus.Panic(err)
148+
}
149+
logrus.Info("Pushed")
150+
151+
createPullRequest(version, "update-"+version.String())
152+
}

dockerhub.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package main
2+
3+
import "encoding/json"
4+
5+
type imageTag struct {
6+
Layer string
7+
Name string
8+
}
9+
10+
func getTags() ([]imageTag, error) {
11+
var tags []imageTag
12+
r, err := myClient.Get("https://index.docker.io/v1/repositories/dtandersen/factorio/tags")
13+
if err != nil {
14+
return tags, err
15+
}
16+
defer r.Body.Close()
17+
18+
err = json.NewDecoder(r.Body).Decode(&tags)
19+
20+
return tags, err
21+
}

factorio.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package main
2+
3+
import (
4+
"crypto/sha1"
5+
"encoding/hex"
6+
"encoding/json"
7+
"io"
8+
"net/http"
9+
"time"
10+
)
11+
12+
func factorioGetChecksum(url string) (string, error) {
13+
var returnSHA1String string
14+
15+
//Open a new SHA1 hash interface to write to
16+
hash := sha1.New()
17+
18+
resp, err := http.Get(url)
19+
if err != nil {
20+
return returnSHA1String, err
21+
}
22+
defer resp.Body.Close()
23+
24+
_, err = io.Copy(hash, resp.Body)
25+
if err != nil {
26+
return returnSHA1String, err
27+
}
28+
29+
//Get the 20 bytes hash
30+
hashInBytes := hash.Sum(nil)[:20]
31+
32+
//Convert the bytes to a string
33+
returnSHA1String = hex.EncodeToString(hashInBytes)
34+
35+
return returnSHA1String, nil
36+
}
37+
38+
var myClient = &http.Client{Timeout: 10 * time.Second}
39+
40+
func GetAvailableVersions() (AvailableVersions, error) {
41+
var availableVersions AvailableVersions
42+
r, err := myClient.Get("https://www.factorio.com/updater/get-available-versions?apiVersion=2")
43+
if err != nil {
44+
return availableVersions, err
45+
}
46+
defer r.Body.Close()
47+
48+
err = json.NewDecoder(r.Body).Decode(&availableVersions)
49+
50+
return availableVersions, err
51+
}
52+
53+
type AvailableVersions struct {
54+
CoreLinuxHeadless64 []AvailableVersionsStep `json:"core-linux_headless64"`
55+
}
56+
type AvailableVersionsStep struct {
57+
From string
58+
To string
59+
Stable string
60+
}

git.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
"os/exec"
9+
"regexp"
10+
11+
"github.com/blang/semver"
12+
)
13+
14+
var (
15+
reDockerfileVersion = regexp.MustCompile(`(VERSION=)(\d+\.\d+\.\d+)`)
16+
reDockerfileSHA1 = regexp.MustCompile(`(SHA1=)([a-z0-9]+)`)
17+
)
18+
19+
func gitCloneRepo(path string) error {
20+
cmd := exec.Command("git", "clone", fmt.Sprintf("https://%s:%s@github.com/%s/%s.git", os.Getenv("GITHUB_USER"), os.Getenv("GITHUB_TOKEN"), githubRepoOwner, githubRepoName), path)
21+
output, err := cmd.CombinedOutput()
22+
if err != nil {
23+
return errors.New(string(output))
24+
}
25+
return nil
26+
}
27+
28+
func gitCheckoutBranch(path string, branch string) error {
29+
cmd := exec.Command("git", "checkout", "-b", branch)
30+
cmd.Dir = path
31+
output, err := cmd.CombinedOutput()
32+
if err != nil {
33+
return errors.New(string(output))
34+
}
35+
return nil
36+
}
37+
38+
func gitCreateCommit(path string, commitMessage string) error {
39+
cmd := exec.Command("git", "commit", "-am", "fk_update")
40+
cmd.Dir = path
41+
output, err := cmd.CombinedOutput()
42+
if err != nil {
43+
return errors.New(string(output))
44+
}
45+
return nil
46+
}
47+
48+
func gitPushBranch(path string, branch string) error {
49+
cmd := exec.Command("git", "push", "--set-upstream", "origin", branch)
50+
cmd.Dir = path
51+
output, err := cmd.CombinedOutput()
52+
if err != nil {
53+
return errors.New(string(output))
54+
}
55+
return nil
56+
}
57+
58+
func editDockerfile(path string, version semver.Version, checksum string) error {
59+
filename := fmt.Sprintf("%s/%d.%d/Dockerfile", path, version.Major, version.Minor)
60+
61+
file, err := ioutil.ReadFile(filename)
62+
if err != nil {
63+
return err
64+
}
65+
file = reDockerfileVersion.ReplaceAll(file, []byte("${1}"+version.String()))
66+
file = reDockerfileSHA1.ReplaceAll(file, []byte("${1}"+checksum))
67+
68+
err = ioutil.WriteFile(filename, file, 0666)
69+
if err != nil {
70+
return err
71+
}
72+
73+
return nil
74+
}
75+
76+
func editReadme(path string, version semver.Version) error {
77+
file, err := ioutil.ReadFile(path + "/README.md")
78+
if err != nil {
79+
return err
80+
}
81+
82+
reReadmeVersion, err := regexp.Compile(fmt.Sprintf("(`)%d\\.%d\\.\\d+(`)", version.Major, version.Minor))
83+
if err != nil {
84+
return err
85+
}
86+
87+
file = reReadmeVersion.ReplaceAll(file, []byte("${1}"+version.String()+"${2}"))
88+
89+
err = ioutil.WriteFile(path+"/README.md", file, 0666)
90+
if err != nil {
91+
return err
92+
}
93+
94+
return nil
95+
}

0 commit comments

Comments
 (0)