Skip to content

Commit

Permalink
Merge pull request #74 from arc42/#72-merge-repos
Browse files Browse the repository at this point in the history
#72 merge repos
  • Loading branch information
gernotstarke authored Dec 10, 2023
2 parents f8afb79 + eaf08a8 commit 16220f0
Show file tree
Hide file tree
Showing 75 changed files with 61,618 additions and 0 deletions.
20 changes: 20 additions & 0 deletions documentation/adrs/0008-deploy-on-fly-io.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 8. Deploy on fly.io

Date: 2023-12-10

## Status

Accepted

## Context

We want to make the statistic-service available online, so we need to either host a service on-premise or in the cloud.

## Decision

Deploy the (PRODUCTION) service on [fly.io](https://fly.io), an affordable cloud service provider with a nice developer experience.

## Consequences

* some secrets (API-tokens) need to be configured via the fly.io command line tool.
* for development, the flyctl utility needs to be installed. See their [documentation](https://fly.io/docs/speedrun/) for details.
Binary file added documentation/icon/status-site-icon.graffle
Binary file not shown.
26 changes: 26 additions & 0 deletions documentation/icon/status-site-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions go-app/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# flyctl launch added from .gitignore
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
**/*.exe
**/*.exe~
**/*.dll
**/*.so
**/*.dylib

# Test binary, built with `go test -c`
**/*.test

# Output of the go coverage tool, specifically when used with LiteIDE
**/*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
**/go.work
**/.DS_Store

# flyctl launch added from .idea/.gitignore
# Default ignored files
.idea/shelf
.idea/workspace.xml
# Editor-based HTTP Client requests
.idea/httpRequests
# Datasource local storage ignored files
.idea/dataSources
.idea/dataSources.local.xml
fly.toml
16 changes: 16 additions & 0 deletions go-app/.github/workflows/fly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: arc42 site usage statistics
on:
push:
branches:
- main
jobs:
deploy:
name: Deploy app
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: flyctl deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
GITHUB_API_KEY: ${{ secrets.GRAPHQL_API_TOKEN }}
24 changes: 24 additions & 0 deletions go-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

# Go workspace file
go.work
.DS_Store
set-plausible-api-key.sh
set-api-keys.sh
8 changes: 8 additions & 0 deletions go-app/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions go-app/.idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions go-app/.idea/jsLibraryMappings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions go-app/.idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions go-app/.idea/site-usage-statistics.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions go-app/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions go-app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# syntax=docker/dockerfile:1

FROM golang:1.21

# Set destination for COPY
WORKDIR /app

# Download Go modules
COPY go.mod go.sum ./
RUN go mod download

# Copy the source code. Note the slash at the end, as explained in
# https://docs.docker.com/engine/reference/builder/#copy
COPY *.go ./
COPY internal/ ./internal/


# Build
RUN CGO_ENABLED=0 GOOS=linux go build -o /arc42-stats

# To bind to a TCP port, runtime parameters must be supplied to the docker command.
# But we can (optionally) document in the Dockerfile what ports
# the application is going to listen on by default.
# https://docs.docker.com/engine/reference/builder/#expose
EXPOSE 8043

# Run
CMD [ "/arc42-stats" ]
45 changes: 45 additions & 0 deletions go-app/cmd/downloadBadgeSVGs/get-badges-from-shields.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Load shields.io badges</title>
</head>
<body>


<h1>Welcome to shields.io badges for arc42 status-page</h1>


<img src="https://img.shields.io/badge/open_issues-CEA41E"/>
<img src="https://img.shields.io/badge/20-open_issues-CEA41E"/>
<img src="https://img.shields.io/badge/20+-open_issues-CEA41E"/>


<img src="https://img.shields.io/badge/issues-6-BDB76B"/>
<img src="https://img.shields.io/badge/issues-...-BDB76B"/>

<h2>Bugs</h2>
<img src="https://img.shields.io/badge/bugs-1-DC143C"/>
<img src="https://img.shields.io/badge/bugs-2-DC143C"/>
<img src="https://img.shields.io/badge/bugs-3-DC143C"/>
<img src="https://img.shields.io/badge/bugs-4-DC143C"/>
<img src="https://img.shields.io/badge/bugs-5-DC143C"/>
<img src="https://img.shields.io/badge/bugs-6-DC143C"/>
<img src="https://img.shields.io/badge/bugs-7-DC143C"/>
<img src="https://img.shields.io/badge/bugs-8-DC143C"/>
<img src="https://img.shields.io/badge/bugs-9-DC143C"/>
<img src="https://img.shields.io/badge/bugs-10-DC143C"/>
<img src="https://img.shields.io/badge/bugs-11-DC143C"/>
<img src="https://img.shields.io/badge/bugs-12-DC143C"/>
<img src="https://img.shields.io/badge/bugs-13-DC143C"/>
<img src="https://img.shields.io/badge/bugs-14-DC143C"/>
<img src="https://img.shields.io/badge/bugs-15-DC143C"/>
<img src="https://img.shields.io/badge/bugs-16-DC143C"/>
<img src="https://img.shields.io/badge/bugs-17-DC143C"/>
<img src="https://img.shields.io/badge/bugs-18-DC143C"/>
<img src="https://img.shields.io/badge/bugs-19-DC143C"/>
<img src="https://img.shields.io/badge/bugs-20-DC143C"/>

</body>
</html>
139 changes: 139 additions & 0 deletions go-app/cmd/downloadBadgeSVGs/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package main

// Saves svg-badges from shields.io to local storage.
//
// These svg files follow this naming schema:
// <nr>-issues.svg (e.g. `13-issues.svg)
// <nr>-bugs.svg (`3-bugs.svg`)
// If there are more issues than `badge.LocalBadgeSvgThreshold`,
// the naming is `20+issues.svg`.

// we download these badges from shields.io, from URLs like this:
// https://img.shields.io/badge/open_issues-19-BDB76B
import (
"arc42-status/internal/badge"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"io"
"net/http"
"os"
"strconv"
)

// SVGBadgePath is the constant path to the directory where SVG files for badges are stored.
const SVGBadgePath = "./svgs/"

const issuesColor = "CEA41E"
const bugsColor = "DC143C"

const badgeDownloadURLPrefix = "https://img.shields.io/badge/"

// svgFileNameForKindOf creates the filename for the downloaded issue-svg files.
// These are required both for the downloading process AND for creating the URLs in the final output HTML
func svgFileNameForKindOf(kindOf string, count int) string {
switch kindOf {
case badge.IssueName:
return strconv.Itoa(count) + badge.IssueBadgeFileNameSuffix
case badge.BugName:
return strconv.Itoa(count) + badge.BugBadgeFileNameSuffix
default:
log.Error().Msgf("error creating filename for count %d and kindOf %s", count, kindOf)
return "_error-" + strconv.Itoa(count)
}
}

func badgeColorForKindOf(kindOf string) string {
switch kindOf {
case badge.IssueName:
return issuesColor
case badge.BugName:
return bugsColor
default:
return issuesColor
}
}

// nrOfBugsIssuesShown returns the infix needed to create the shields.io URL
func nrOfBugsIssuesShown(count int, kindOf string) string {
if count == 1 {
// note: Singular
return "open_" + kindOf + "-1-"
} else if (count == 0) || (count <= badge.LocalBadgeSvgThreshold) {
// count + Plural
return "open_" + kindOf + "s-" + strconv.Itoa(count) + "-"
} else {
// 20+
return "open_" + kindOf + "s-" + strconv.Itoa(badge.LocalBadgeSvgThreshold) + "+-"
}
}

func openIssueSVGBadgeDownloadURL(count int, kindOf string) string {
var infix = nrOfBugsIssuesShown(count, kindOf)
return badgeDownloadURLPrefix + infix + badgeColorForKindOf(kindOf)
}

func createSVGBadgeDirIfNotPresent(dirName string) {

if _, err := os.Stat(dirName); os.IsNotExist(err) {
errDir := os.MkdirAll(dirName, 0755)
if errDir != nil {
log.Fatal().Msg(errDir.Error())
} else {
log.Info().Msgf("directory %s created", dirName)
}

}
}

// Function to download and save SVG file
func downloadSVG(url string, count int, kindOf string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()

fileName := svgFileNameForKindOf(kindOf, count)
log.Info().Msgf("filename is %s", fileName)

file, err := os.Create(SVGBadgePath + fileName)
if err != nil {
return err
}
defer file.Close()

_, err = io.Copy(file, resp.Body)
return err
}

func init() {
// Configure the global logger to write to console/stdout and add file and line number
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: zerolog.TimeFormatUnix}
log.Logger = zerolog.New(output).With().Timestamp().Caller().Logger()
}

func downloadSVGBadgesForKindof(kindOf string) {
log.Info().Msgf("starting to download %ss", kindOf)

// Download and save each SVG file
for count := 1; count <= badge.LocalBadgeSvgThreshold+1; count++ {

// first, load badge for issue
url := openIssueSVGBadgeDownloadURL(count, kindOf)
log.Info().Msgf("loading badge-SVG for %d %ss from %s", count, kindOf, url)
err := downloadSVG(url, count, kindOf)
if err != nil {
panic(err)
}
}
}

func main() {
// create SVGBadge directory, if it does not exist,
// so we have a filesystem location to store SVG files
createSVGBadgeDirIfNotPresent(SVGBadgePath)

downloadSVGBadgesForKindof(badge.IssueName)
downloadSVGBadgesForKindof(badge.BugName)

}
1 change: 1 addition & 0 deletions go-app/cmd/downloadBadgeSVGs/svgs/1-bugs.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 16220f0

Please sign in to comment.