cache buster
This commit is contained in:
78
.github/workflows/docker-build-self.yml
vendored
78
.github/workflows/docker-build-self.yml
vendored
@@ -11,48 +11,48 @@ jobs:
|
|||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Build Docker image
|
- name: Write build number
|
||||||
run: |
|
run: echo "${{ github.run_number }}" >> build_number
|
||||||
IMAGE_NAME="go-web-server"
|
|
||||||
RUN_NUMBER="${{ github.run_number }}"
|
|
||||||
docker build -t "$IMAGE_NAME:latest" -t "$IMAGE_NAME:${{ github.run_number }}" .
|
|
||||||
|
|
||||||
- name: Ensure no existing temp container
|
- name: Build Docker image
|
||||||
run: |
|
run: |
|
||||||
if [ "$(docker ps -aq -f name=temp-go-web-server)" ]; then
|
IMAGE_NAME="go-web-server"
|
||||||
docker stop temp-go-web-server || true
|
docker build -t "$IMAGE_NAME:latest" -t "$IMAGE_NAME:${{ github.run_number }}" .
|
||||||
docker rm temp-go-web-server || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
- name: Ensure no existing temp container
|
||||||
|
run: |
|
||||||
|
if [ "$(docker ps -aq -f name=temp-go-web-server)" ]; then
|
||||||
|
docker stop temp-go-web-server || true
|
||||||
|
docker rm temp-go-web-server || true
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Run temporary container for health check
|
- name: Run temporary container for health check
|
||||||
run: |
|
run: |
|
||||||
docker run -d --name temp-go-web-server -p 54322:54321 go-web-server:latest
|
docker run -d --name temp-go-web-server -p 54322:54321 go-web-server:latest
|
||||||
sleep 10 # Wait for the container to start
|
sleep 10 # Wait for the container to start
|
||||||
if curl -f http://localhost:54322/health; then
|
if curl -f http://localhost:54322/health; then
|
||||||
echo "Health check passed"
|
echo "Health check passed"
|
||||||
docker stop temp-go-web-server
|
docker stop temp-go-web-server
|
||||||
docker rm temp-go-web-server
|
docker rm temp-go-web-server
|
||||||
else
|
else
|
||||||
echo "Health check failed"
|
echo "Health check failed"
|
||||||
docker logs temp-go-web-server
|
docker logs temp-go-web-server
|
||||||
docker stop temp-go-web-server
|
docker stop temp-go-web-server
|
||||||
docker rm temp-go-web-server
|
docker rm temp-go-web-server
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Stop and remove current container
|
- name: Stop and remove current container
|
||||||
run: |
|
run: |
|
||||||
if [ "$(docker ps -q -f name=go-web-server)" ]; then
|
if [ "$(docker ps -q -f name=go-web-server)" ]; then
|
||||||
docker stop go-web-server || true
|
docker stop go-web-server || true
|
||||||
docker rm go-web-server || true
|
docker rm go-web-server || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Run new container
|
|
||||||
run: |
|
|
||||||
IMAGE_NAME="go-web-server"
|
|
||||||
docker run -d --name go-web-server -p 54321:54321 --restart=always -v "/volume2/docker/knet/data:/app/data" "$IMAGE_NAME:latest"
|
|
||||||
|
|
||||||
|
- name: Run new container
|
||||||
|
run: |
|
||||||
|
IMAGE_NAME="go-web-server"
|
||||||
|
docker run -d --name go-web-server -p 54321:54321 --restart=always -v "/volume2/docker/knet/data:/app/data" "$IMAGE_NAME:latest"
|
||||||
|
|||||||
1
build_number
Normal file
1
build_number
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1
|
||||||
@@ -15,6 +15,7 @@ COPY ./src ./src
|
|||||||
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /server ./src
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /server ./src
|
||||||
|
|
||||||
COPY ./views ./views
|
COPY ./views ./views
|
||||||
|
COPY ./build_number ./build_number
|
||||||
|
|
||||||
FROM scratch
|
FROM scratch
|
||||||
|
|
||||||
|
|||||||
16
js/boxes.js
16
js/boxes.js
@@ -33,20 +33,8 @@
|
|||||||
socket.send("b:" + id + ":" + value);
|
socket.send("b:" + id + ":" + value);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
var autoPlayTimer = undefined;
|
const autoPlayEl = document.querySelector("#randomize");
|
||||||
const handleAutoPlay = (el) => {
|
autoPlayEl?.addEventListener("click", (e) => socket.send("r:1000"));
|
||||||
if (el.checked) {
|
|
||||||
autoPlayTimer = setInterval(() => {
|
|
||||||
socket.send("random");
|
|
||||||
}, 50);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
clearInterval(autoPlayTimer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const autoPlayEl = document.querySelector("#auto-boxes");
|
|
||||||
handleAutoPlay(autoPlayEl);
|
|
||||||
autoPlayEl?.addEventListener("change", (e) => handleAutoPlay(e.target));
|
|
||||||
var golTimer = undefined;
|
var golTimer = undefined;
|
||||||
const handleGol = (el) => {
|
const handleGol = (el) => {
|
||||||
if (el.checked) {
|
if (el.checked) {
|
||||||
|
|||||||
18
js/boxes.ts
18
js/boxes.ts
@@ -46,22 +46,8 @@ type Box = {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var autoPlayTimer: number | undefined = undefined;
|
const autoPlayEl = document.querySelector("#randomize") as CheckboxEl;
|
||||||
const handleAutoPlay = (el: CheckboxEl) => {
|
autoPlayEl?.addEventListener("click", (e) => socket.send("r:1000"));
|
||||||
if (el.checked) {
|
|
||||||
autoPlayTimer = setInterval(() => {
|
|
||||||
socket.send("random");
|
|
||||||
}, 50);
|
|
||||||
} else {
|
|
||||||
clearInterval(autoPlayTimer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const autoPlayEl = document.querySelector("#auto-boxes") as CheckboxEl;
|
|
||||||
handleAutoPlay(autoPlayEl);
|
|
||||||
autoPlayEl?.addEventListener("change", (e) =>
|
|
||||||
handleAutoPlay(e.target as CheckboxEl)
|
|
||||||
);
|
|
||||||
|
|
||||||
var golTimer: number | undefined = undefined;
|
var golTimer: number | undefined = undefined;
|
||||||
const handleGol = (el: CheckboxEl) => {
|
const handleGol = (el: CheckboxEl) => {
|
||||||
|
|||||||
@@ -57,13 +57,12 @@ func (box Box) persist() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := stmt.Exec(box.Id, box.Value)
|
_, err = stmt.Exec(box.Id, box.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
stmt.Close()
|
stmt.Close()
|
||||||
|
|
||||||
log.Info(res.LastInsertId())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBox(id int) (Box, error) {
|
func getBox(id int) (Box, error) {
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ func handleWsError(err error, conn *websocket.Conn) {
|
|||||||
func broadcastMessage(message string) {
|
func broadcastMessage(message string) {
|
||||||
wsMutex.Lock()
|
wsMutex.Lock()
|
||||||
defer wsMutex.Unlock()
|
defer wsMutex.Unlock()
|
||||||
|
|
||||||
for conn := range wsConnections {
|
for conn := range wsConnections {
|
||||||
err := websocket.Message.Send(conn, message)
|
err := websocket.Message.Send(conn, message)
|
||||||
handleWsError(err, conn)
|
handleWsError(err, conn)
|
||||||
@@ -66,6 +65,22 @@ func broadcastMessage(message string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func randomizeBoxes(count int) []Box {
|
||||||
|
boxes := make([]Box, count)
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
index := random.Int() % 1000
|
||||||
|
box, err := getBox(index)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
box.Value = !box.Value
|
||||||
|
box.persist()
|
||||||
|
boxes[i] = box
|
||||||
|
}
|
||||||
|
return boxes
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func handleMessage(msg string, ws *websocket.Conn) error {
|
func handleMessage(msg string, ws *websocket.Conn) error {
|
||||||
if msg == "gol" {
|
if msg == "gol" {
|
||||||
matrix := make(map[string]Box)
|
matrix := make(map[string]Box)
|
||||||
@@ -77,7 +92,6 @@ func handleMessage(msg string, ws *websocket.Conn) error {
|
|||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Error(matrix)
|
|
||||||
nextGen := make([]Box, 0)
|
nextGen := make([]Box, 0)
|
||||||
for id, item := range matrix {
|
for id, item := range matrix {
|
||||||
nextItem := shouldBeAlive(matrix, id)
|
nextItem := shouldBeAlive(matrix, id)
|
||||||
@@ -94,16 +108,17 @@ func handleMessage(msg string, ws *websocket.Conn) error {
|
|||||||
}
|
}
|
||||||
broadcastMessage(nextMessage)
|
broadcastMessage(nextMessage)
|
||||||
|
|
||||||
} else if msg == "random" {
|
} else if strings.Contains(msg, "r:") {
|
||||||
index := random.Int() % 1000
|
count, err := strconv.Atoi(strings.Split(msg, ":")[1])
|
||||||
box, err := getBox(index)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Errorf("Failed to parse randomize count: %v", err)
|
||||||
|
}
|
||||||
|
boxes := randomizeBoxes(count)
|
||||||
|
message := ""
|
||||||
|
for _, box := range boxes {
|
||||||
|
message += box.serialize()
|
||||||
}
|
}
|
||||||
box.Value = !box.Value
|
|
||||||
box.persist()
|
|
||||||
|
|
||||||
message := box.serialize()
|
|
||||||
broadcastMessage(message)
|
broadcastMessage(message)
|
||||||
|
|
||||||
} else if strings.Contains(msg, "b:") {
|
} else if strings.Contains(msg, "b:") {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
|
|
||||||
|
"knet.sk/src/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -86,9 +88,9 @@ func InitWs(c echo.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Data struct {
|
type Data struct {
|
||||||
Template string
|
BuildNumber string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Page(c echo.Context) error {
|
func Page(c echo.Context) error {
|
||||||
return c.Render(200, "index2", Data{Template: "draw"})
|
return c.Render(200, "index2", Data{BuildNumber: util.GetBuildNumber()})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/labstack/gommon/log"
|
"github.com/labstack/gommon/log"
|
||||||
"knet.sk/src/boxes"
|
"knet.sk/src/boxes"
|
||||||
"knet.sk/src/draw"
|
"knet.sk/src/draw"
|
||||||
|
"knet.sk/src/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Templates struct {
|
type Templates struct {
|
||||||
@@ -26,12 +27,14 @@ func NewTemplates() *Templates {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Page struct {
|
type Page struct {
|
||||||
Boxes []boxes.Box
|
Boxes []boxes.Box
|
||||||
|
BuildNumber string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPage(boxes []boxes.Box) Page {
|
func newPage(boxes []boxes.Box) Page {
|
||||||
return Page{
|
return Page{
|
||||||
Boxes: boxes,
|
Boxes: boxes,
|
||||||
|
BuildNumber: util.GetBuildNumber(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,6 +44,7 @@ var (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
e.Renderer = NewTemplates()
|
e.Renderer = NewTemplates()
|
||||||
|
// read the ./build_number file
|
||||||
|
|
||||||
e.Logger.SetLevel(log.DEBUG)
|
e.Logger.SetLevel(log.DEBUG)
|
||||||
e.Use(middleware.Logger())
|
e.Use(middleware.Logger())
|
||||||
|
|||||||
20
src/util/build-number.go
Normal file
20
src/util/build-number.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var buildNumber string
|
||||||
|
|
||||||
|
func GetBuildNumber() string {
|
||||||
|
if buildNumber == "" {
|
||||||
|
b, err := os.ReadFile("build_number") // just pass the file name
|
||||||
|
if err != nil {
|
||||||
|
fmt.Print(err)
|
||||||
|
}
|
||||||
|
buildNumber = string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildNumber
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
{{block "boxes" .}}
|
{{block "boxes" .}}
|
||||||
<link rel="stylesheet" href="/css/boxes.css" />
|
<link rel="stylesheet" href="/css/boxes.css?v={{.BuildNumber}}" />
|
||||||
<div class="boxes-container">
|
<div class="boxes-container">
|
||||||
<label>
|
<label>
|
||||||
Auto play boxes
|
|
||||||
<input type="checkbox" id="auto-boxes" />
|
<Button id="randomize">Randomize</Button>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Auto play Game of Life
|
Auto play Game of Life
|
||||||
<input type="checkbox" id="game-of-life" />
|
<input type="checkbox" id="game-of-life" />
|
||||||
</label>
|
</label>
|
||||||
<div class="boxes">
|
<div class="boxes">
|
||||||
{{range .}}<label
|
{{range .Boxes}}<label
|
||||||
><input
|
><input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="box-{{.Id}}"
|
id="box-{{.Id}}"
|
||||||
@@ -24,6 +24,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="js/ws.js"></script>
|
<script src="js/ws.js?v={{.BuildNumber}}"></script>
|
||||||
<script src="js/boxes.js"></script>
|
<script src="js/boxes.js?v={{.BuildNumber}}"></script>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
@@ -23,9 +23,9 @@
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
"
|
"
|
||||||
></div>
|
></div>
|
||||||
<script src="js/ws.js"></script>
|
<script src="js/ws.js?v={{.BuildNumber}}"></script>
|
||||||
<script src="/js/mitt/mitt.js"></script>
|
<script src="/js/mitt/mitt.js?v={{.BuildNumber}}"></script>
|
||||||
<script src="/js/draw.js"></script>
|
<script src="/js/draw.js?v={{.BuildNumber}}"></script>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
<link rel="stylesheet" href="/css/main.css" />
|
<link rel="stylesheet" href="/css/main.css?v={{.BuildNumber}}" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
<section>
|
<section>
|
||||||
{{template "draw" }}
|
{{template "draw" . }}
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
<link rel="stylesheet" href="/css/main.css" />
|
<link rel="stylesheet" href="/css/main.css?v={{.BuildNumber}}" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
<main>
|
<main>
|
||||||
<section>
|
<section>
|
||||||
{{template "boxes" .Boxes}}
|
{{template "boxes" .}}
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user