Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
sethgrid committed Dec 1, 2024
0 parents commit 2bca8d1
Show file tree
Hide file tree
Showing 1,292 changed files with 438,623 additions and 0 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/github-actions-demo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: helloworld Build
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]

jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest

steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."

- name: Check out repository code
uses: actions/checkout@v3

- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."

- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."

- name: Build integration service
run: docker compose build integration

- name: Run integration tests
run: docker compose run --rm integration
continue-on-error: true # Continue even if the test fails to capture logs

- name: Show Docker logs on failure
if: failure() # Only run this step if the previous step failed
run: docker compose logs

- name: Tear down Docker Compose
if: always() # This step runs regardless of success or failure to clean up
run: docker compose down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
bin/*
settings.env
logs/*
docker-configs/loki/*
175 changes: 175 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
### Restoration from scratch

helloworld.com runs on a digital ocean droplet running Ubuntu. It connects to a managed MySQL cluster. Locally, the service is managed by `systemctl` and logs are collected via `journalctl`. Secrets are in my Bitwarden.

See appendix for files.

Ensure the node only allows ssh over keys; disable passwords in `/etc/ssh/sshd_config`.

Get journalctl set up and:
```
sudo systemctl restart systemd-journald
```

Set up `/home/seth/projects/helloworld` (and `punicode` and `me` / personal site).
You can create `./bin/helloworld` via scp or you can download the repo and build locally

Get the services in place and run:
```
sudo systemctl daemon-reload
sudo systemctl restart helloworld.service # and punicode.service
```

Starting caddy:
```
sudo caddy stop && sudo caddy start --config Caddyfile
```

That should be enough to limp back to life.

Grafana UI can be ran from your local via a tunnel. However, for production db metrics, we have to have a
digital ocean personal access token with full db access. Use this guide to set up db monitoring but as of yet I am having trouble getting it working; maybe later:
https://www.digitalocean.com/community/tutorials/monitoring-mysql-and-mariadb-droplets-using-prometheus-mysql-exporter


and for getting set up with migrations, make sure to install goose
https://github.com/pressly/goose



### Other Services

- 0Auth, user [email protected]
- DigialOcean, user [email protected]
- Namecheap, user [email protected]

### Appendix

`/home/seth/projects/helloworld/settings.env`
```
{{ Contents from Bitwarden; note: no "export", just key=val }}
```

`~/.my.cnf` (contains secret)
```
[client]
user = doadmin
password = {{ SEE BITWARDEN }}
host = db-mysql-helloworld-do-user-619265-0.g.db.ondigitalocean.com
port = 25060
database = helloworld
ssl-ca = ~/ca-certificate.crt
ssl-mode = VERIFY_CA
```

`/etc/systemd/system/helloworld.service`
```
[Unit]
Description=helloworld.com Service
After=network.target
[Service]
EnvironmentFile=/home/seth/projects/helloworld/settings.env
ExecStart=/home/seth/projects/helloworld/bin/helloworld
WorkingDirectory=/home/seth/projects/helloworld
Restart=always
User=seth
Group=seth
[Install]
WantedBy=multi-user.target
```


`/etc/systemd/journald.conf`

```
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See journald.conf(5) for details.
[Journal]
#Storage=auto
#Compress=yes
#Seal=yes
#SplitMode=uid
#SyncIntervalSec=5m
#RateLimitIntervalSec=30s
#RateLimitBurst=1000
SystemMaxUse=100M
#SystemKeepFree=
SystemMaxFileSize=50M
#SystemMaxFiles=100
#RuntimeMaxUse=
#RuntimeKeepFree=
#RuntimeMaxFileSize=
#RuntimeMaxFiles=100
MaxRetentionSec=1month
#MaxFileSec=1month
#ForwardToSyslog=yes
#ForwardToKMsg=no
#ForwardToConsole=no
#ForwardToWall=yes
#TTYPath=/dev/console
#MaxLevelStore=debug
#MaxLevelSyslog=debug
#MaxLevelKMsg=notice
#MaxLevelConsole=info
#MaxLevelWall=emerg
#LineMax=48K
```

`~/.ssh/authorized_keys`
```
See BitWarden
```

`/home/seth/projects/Caddyfile`
```
www.helloworld.com, api.helloworld.com, helloworld.com {
reverse_proxy localhost:6666
}
sethammons.com, www.sethammons.com {
root * /home/seth/projects/me/site/public
file_server
}
xn--pnicode-n2a.com {
reverse_proxy localhost:5555
}
```

#### Other Services

Punicode

`/etc/systemd/system/punicode.service`
```
[Unit]
Description=Pünicode.com Service
After=network.target
[Service]
ExecStart=/home/seth/projects/punicode/bin/punicode
WorkingDirectory=/home/seth/projects/punicode
Restart=always
User=seth
Group=seth
[Install]
WantedBy=multi-user.target
```
20 changes: 20 additions & 0 deletions Dockerfile.base
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# docker build -t sethgrid/golang-chromium:v0.1.0 -f Dockerfile.base .
# docker push sethgrid/golang-chromium:v0.1.0

FROM golang:latest

# NOTE: this must contain 'helloworld' to match the value in getRootDir() otherwise we can't fetch templates and stuff
WORKDIR /go/src/helloworld

# Copy only the go.mod and go.sum files to leverage Docker cache
COPY go.mod go.sum ./

# Download dependencies
RUN go mod download

# Copy the rest of the application code
COPY . .

# by running the unitintegration tests, we force the rod package to place chromium in a known location
# this allows our main application to then run unitintegration withoug having to download chromium.
RUN go test ./... -tags=unitintegration -v -timeout=120s
13 changes: 13 additions & 0 deletions Dockerfile.db-load-seed
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM alpine:latest

# Install make, MySQL client, and other necessary tools
RUN apk update && apk add --no-cache mysql-client bash make docker

# Set working directory
WORKDIR /app

# Copy your Makefile and other necessary files
COPY . .

# Default command
CMD ["sh", "-c", "mysql -h mysql -uroot -proot < /app/sql/seed.sql"]
10 changes: 10 additions & 0 deletions Dockerfile.helloworld
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM golang:latest

WORKDIR /go/src/helloworld

COPY . .

RUN go build -ldflags="-X 'main.Version=${helloworld_VERSION}'" \
-o /go/src/helloworld/bin/helloworld cmd/helloworld/main.go

CMD ["bin/helloworld"]
22 changes: 22 additions & 0 deletions Dockerfile.helloworld-build
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# not pulling latest because there was a glibc issue when running the generated binary on DO
FROM golang:1.21-bullseye

WORKDIR /go/src/helloworld

### DISABLED THIS OPTIMIZATION
### Was getting timeouts to the go proxy even if disabled, direct, set explicitly...
### Vendoring is better anyway
# Copy only the go.mod and go.sum files to leverage Docker cache
# COPY go.mod go.sum ./

# Download dependencies
# RUN GOPROXY=https://goproxy.io go mod download

# Copy the rest of the application code
COPY . .

RUN export helloworld_VERSION=$(cat VERSION) && \
GOOS=linux GOARCH=amd64 go build -ldflags="-X 'main.Version=${helloworld_VERSION}'" \
-o /go/src/helloworld/bin/helloworld cmd/helloworld/main.go

CMD ["bin/helloworld"]
12 changes: 12 additions & 0 deletions Dockerfile.integration
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM golang:1.21-bullseye

# NOTE: this must contain 'helloworld' to match the value in getRootDir() otherwise we can't fetch templates and stuff
WORKDIR /go/src/helloworld
COPY . .

# the tests need to pull a headless browser on first run; give more time for that
# TODO - build a base image that has already ran the headless browser
RUN go test -tags=unitintegration -timeout=3m -race -v ./...
RUN go build -o /go/src/helloworld/bin/integration_tests cmd/integration_tests/main.go

CMD ["bin/integration_tests"]
79 changes: 79 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Makefile

LANG=en_US.UTF-8
SHELL=/bin/bash
.SHELLFLAGS=--norc --noprofile -e -u -o pipefail -c

# Make does not run in your shell. If you have go's path set in your shell
GOLOCATION=/usr/local/go/bin

BUILD_DIR := ./bin

.PHONY: build targets

targets:
@make -qp | awk -F: '/^[a-zA-Z0-9][^$#\/\t=]*:([^=]|$$)/ {split($$1,A,/ /);for(i in A)print A[i]}' | sort

build:
@echo "Building helloworld..."
mkdir -p $(BUILD_DIR)
chmod 755 $(BUILD_DIR)
rm $(BUILD_DIR)/helloworld || true
export PATH=${PATH}:${GOLOCATION} && go build -ldflags="-X 'main.Version=$(shell cat VERSION)'" -o ${BUILD_DIR}/helloworld ./cmd/helloworld

kill:
pkill helloworld

db-restart:
docker compose stop mysql || true
docker compose rm -f mysql || true
docker compose up -d mysql

db-manage:
@echo "docker compose exec mysql mysql -uroot helloworld -proot helloworld"
@echo "(use pw: root)"
docker compose exec mysql mysql -uroot -proot helloworld


test:
@echo "running go test ./..."
go test ./...

test-unitintegration:
@echo "running go test ./..."
go test ./... -tags=unitintegration -count=1


clean: db-restart
@echo "Cleaning up..."
rm -f ./bin/helloworld || true
docker compose stop --force helloworld || true
docker compose rm --force helloworld || true

test-integration-dirty:
@echo "Ensure that you are running a local instance of helloworld"
@echo "Building integration_tests..."
export PATH=${PATH}:${GOLOCATION} && go build -o $(BUILD_DIR)/integration_tests cmd/integration_tests/main.go

$(eval DB_ID := $(shell sudo docker ps | grep mysql | cut -d' ' -f1))
$(eval DB_ADDR := $(shell docker inspect ${DB_ID} -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ))

DB_ADDR="${DB_ADDR}" DB_PORT="3306" ./bin/integration_tests

test-integration: clean
@echo "Ensure that you are running a local instance of helloworld"
@echo "Building integration_tests..."
export PATH=${PATH}:${GOLOCATION} && go build -o $(BUILD_DIR)/integration_tests cmd/integration_tests/main.go

$(eval DB_ID := $(shell sudo docker ps | grep mysql | cut -d' ' -f1))
$(eval DB_ADDR := $(shell docker inspect ${DB_ID} -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ))

DB_ADDR="${DB_ADDR}" DB_PORT="3306" ./bin/integration_tests


test-integration-docker: clean build
@echo "Docker integration_tests..."
docker compose up -d mysql
docker compose up -d helloworld
docker compose build integration
docker compose run --rm integration
Loading

0 comments on commit 2bca8d1

Please sign in to comment.