Skip to content

Commit

Permalink
Create a home app (#1032)
Browse files Browse the repository at this point in the history
Create a home app using Go & Gin with templated HTML and minimal JS. 

This PR mimics the style of the original home app as much as possible.
However, it updates the UI to use Bootstrap 5. I did add a favicon & a
page title as well to make the MATS landing page look more official.

I've done a few additional things as they were easy to do now that we
have a Go server:
- I added a `/health` endpoint to the application so that we can use
[automated health
checks](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)
in Kubernetes.
- I added some basic Prometheus metrics so we can tell if the app is up
and if it's taking longer than expected to respond to users. In the
future we may be able to instrument the app links so we can tell how
often certain apps are used. Otherwise, we could implement something
like Google Analytics to get that info.
- Added containerization and CI around the project so we can deploy it.

This is intended to slot into our current docker-compose stacks and
replace `matsapps/production:mats-http` which is this Go file server:
https://github.com/halverneus/static-file-server. Obviously, we could
also deploy this in Kubernetes.

This PR is stacked on top of #1031 and under #1037.
  • Loading branch information
ian-noaa authored Sep 12, 2023
2 parents 7d8b524 + a046b75 commit 2d007dc
Show file tree
Hide file tree
Showing 68 changed files with 60,829 additions and 2 deletions.
13 changes: 13 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,23 @@

version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
pull-request-branch-name:
separator: "-" # Use "-" instead of "/" in branch names to avoid issues with docker registries
target-branch: "development" # raise PRs for version updates to GHA against the `development` branch
assignees:
- "ian-noaa"

# Maintain dependencies for Go
- package-ecosystem: "gomod"
directory: "/home"
schedule:
interval: "weekly"
pull-request-branch-name:
separator: "-" # Use "-" instead of "/" in branch names to avoid issues with docker registries
assignees:
- "ian-noaa"
7 changes: 5 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
name: "Build"
name: "Build MATS Apps"
on:
push:
branches: [main, development]
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+'
paths-ignore:
- "home/**"
pull_request:
branches: [main, development]
paths-ignore:
- "home/**"
workflow_dispatch:
env:
DEV_REGISTRY: ghcr.io/noaa-gsl/mats/development
Expand Down
118 changes: 118 additions & 0 deletions .github/workflows/home.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: "Build Home App"

on:
push:
branches: ["main", "development"]
paths:
- "home/**"
pull_request:
paths:
- "home/**"
workflow_dispatch:
env:
DEV_REGISTRY: ghcr.io/noaa-gsl/mats/development

# Update the working directory for any job steps with "run" components.
# Note this doesn't apply to "uses" steps - those will need to have
# their working directory updated manually, if they support it.
defaults:
run:
working-directory: "home"

jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: "1.20"
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
working-directory: "home"

test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version: "1.20"
- name: Build
run: go build -v ./...
- name: Test
run: go test -v -shuffle=on -cover ./...

build:
name: Build Docker image
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
packages: write
security-events: write
steps:
- uses: actions/checkout@v3

- name: Set env variables
shell: bash
# Note - this doesn't support branch names with "/" in them
run: |
DATE=$(git show -s --format=%cd --date=format:'%Y-%m-%d.%H:%M:%S.%z' ${{ github.sha }})
if [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then
# PR build
echo "BRANCH=${GITHUB_HEAD_REF}" >> $GITHUB_ENV
echo "VERSION=dev-${{ github.sha }}-$DATE" >> $GITHUB_ENV
elif [[ "${GITHUB_EVENT_NAME}" == "push" ]]; then
# Handle differences between branches/tags
if [[ "${GITHUB_REF}" == *"heads"* ]]; then
# Branch build
echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
echo "VERSION=dev-${{ github.sha }}-$DATE" >> $GITHUB_ENV
elif [[ "${GITHUB_REF}" == *"tags"* ]]; then
# Tag build
echo "BRANCH=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
else
echo "ERROR: Unanticipated Git Ref"
exit 1
fi
else
echo "ERROR: Unanticipated GitHub Event"
exit 1
fi
- name: Build image
run: |
docker build \
--build-arg BUILDVER="${{ env.VERSION }}" \
--build-arg COMMITBRANCH=${{ env.BRANCH }} \
--build-arg COMMITSHA=${{ github.sha }} \
-t ${{ env.DEV_REGISTRY }}/home:${{ env.BRANCH }} \
.
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: '${{ env.DEV_REGISTRY }}/home:${{ env.BRANCH }}'
format: 'sarif'
output: 'trivy-results-home.sarif'
ignore-unfixed: true

- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results-home.sarif'

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Push image to dev registry
run: |
docker push ${{ env.DEV_REGISTRY }}/home:${{ env.BRANCH }}
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ kubernetes
scripts
server_configuration_files
static
!home/static
**/.meteor
**/met-*
**/README.md
Expand Down
18 changes: 18 additions & 0 deletions home/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Tooling artifacts
.git/
.github/
.idea/
.vscode/
.gitignore

# Home app
docs/
.golangci.yml
Dockerfile
docker-compose.yml
**/*.md
LICENSE
home
main
coverage.out
settings.json
3 changes: 3 additions & 0 deletions home/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Go binaries for this project
home
main
198 changes: 198 additions & 0 deletions home/.golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
run:
tests: true

output:
uniq-by-line: false
sort-results: true
print-linter-name: true

issues:
# Show all issues in the project
max-issues-per-linter: 0
max-same-issues: 0
new: false


# Linters & linter-settings inspired by https://olegk.dev/go-linters-configuration-the-right-version
linters:
enable:
# Check for passing []any as any in variadic func(...any).
- asasalint

# Prefer plain ASCII identifiers.
# I.e. - use `delta` in place of `∆`
# TODO - enable
# - asciicheck

# Checks for dangerous unicode character sequences.
- bidichk

# Check that HTTP response bodies are closed
- bodyclose

# Check whether the function uses a non-inherited context.
- contextcheck

# Check for two durations multiplied together.
- durationcheck

# Forces to not skip error check.
- errcheck

# Checks `Err-` prefix for var and `-Error` suffix for error type.
- errname

# Suggests to use `%w` for error-wrapping.
- errorlint

# Checks for pointers to enclosing loop variables.
- exportloopref

- gocritic

# lint comments
# TODO - enable
# - godot

# Make sure everything's auto-formatted
- gofmt
- gofumpt
- goimports

# Handle replace, retract, exclude directives in go.mod
- gomoddirectives

# Security-oriented linter
# TODO - enable
# - gosec

# Simplify code
- gosimple

# Official go linter
- govet

# Detects when assignments to existing variables are unused
- ineffassign

# Check for misspellings
- misspell

# Finds naked/bare returns
- nakedret

# Both require a bit more explicit returns.
- nilerr
- nilnil

# Finds sending HTTP request without context.Context.
- noctx

# Forces comment why another check is disabled.
# Better not to have //nolint: at all ;)
- nolintlint

# Finds slices that could potentially be pre-allocated.
# - prealloc

# Finds shadowing of Go's predeclared identifiers.
# I hear a lot of complaints from junior developers.
# But after some time they find it very useful.
- predeclared

# Lint your Prometheus metrics name.
- promlinter

# Checks that package variables are not reassigned.
# Super rare case but can catch bad things (like `io.EOF = nil`)
- reassign

# Drop-in replacement of `golint`
- revive

# Somewhat similar to `bodyclose` but for `database/sql` package.
- rowserrcheck
- sqlclosecheck

- staticcheck

# Checks function and package cyclomatic complexity
# Cyclomatic complexity is a measurement, not a goal.
# TODO - enable
# - cyclop

- typecheck

# Is a replacement for `golint`, similar to `revive`.
- stylecheck

# Check struct tags.
- tagliatelle

# Test-related checks.
- tenv
- testableexamples
- thelper
- tparallel

# Remove unnecessary type conversions, make code cleaner
- unconvert

# Might be noisy but better to know what is unused
# TODO - enable
# - unparam

# Must have. Finds unused declarations.
- unused

# Detect the possibility to use variables/constants from stdlib.
# TODO - enable
- usestdlibvars

# Finds wasted assignment statements.
- wastedassign

linters-settings:
# See https://go-critic.com/overview.html
gocritic:
enabled-tags:
- diagnostic
# - experimental
- opinionated
- performance
- style
disabled-checks:
# These 3 detect many cases and are mostly useful for helping optimize for
# performance oriented code
- hugeParam
- rangeExprCopy
- rangeValCopy

errcheck:
# Report `a := b.(MyStruct)` when `a, ok := ...` should be.
# TODO - enable
# check-type-assertions: true # Default: false

# Report skipped checks:`num, _ := strconv.Atoi(numStr)`.
# TODO - enable
# check-blank: true # Default: false

# Function to skip.
exclude-functions:
- io/ioutil.ReadFile
- io.Copy(*bytes.Buffer)
- io.Copy(os.Stdout)

nakedret:
# No naked returns
max-func-lines: 1 # Default: 30

tagliatelle:
case:
rules:
json: snake
yaml: snake
xml: camel
bson: camel
avro: snake
mapstructure: kebab
Loading

0 comments on commit 2d007dc

Please sign in to comment.