Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Goal
<!-- What does this PR accomplish? 1 sentence. -->

## Changes
-

## Testing
<!-- How did you verify it? -->

## Checklist
- [ ] Title is a clear sentence (<= 70 chars)
- [ ] Commits are signed (`git log --show-signature`)
- [ ] `submissions/labN.md` updated
116 changes: 116 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
name: CI

on:
push:
branches:
- main
paths:
- "app/**"
- ".github/workflows/**"
pull_request:
branches:
- main
paths:
- "app/**"
- ".github/workflows/**"

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
vet:
name: vet
runs-on: ubuntu-24.04
timeout-minutes: 10

defaults:
run:
working-directory: app

steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.5.0
with:
go-version: "1.26.4"
cache: true
cache-dependency-path: app/go.mod

- name: Run go vet
run: go vet ./...
env:
GOFLAGS: -buildvcs=false

test:
name: test
runs-on: ubuntu-24.04
timeout-minutes: 10

defaults:
run:
working-directory: app

steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.5.0
with:
go-version: "1.26.4"
cache: true
cache-dependency-path: app/go.mod

- name: Run tests
run: go test -race -count=1 ./...
env:
GOFLAGS: -buildvcs=false

lint:
name: lint
runs-on: ubuntu-24.04
timeout-minutes: 10

steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2

- name: Run golangci-lint
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v8.0.0
with:
version: v2.5.0
working-directory: app

govulncheck:
name: govulncheck
runs-on: ubuntu-24.04
timeout-minutes: 10

defaults:
run:
working-directory: app

steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.2.2

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.5.0
with:
go-version: "1.26.4"
cache: true
cache-dependency-path: app/go.mod

- name: Install govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@v1.1.4

- name: Run govulncheck
run: $(go env GOPATH)/bin/govulncheck ./...
env:
GOFLAGS: -buildvcs=false
98 changes: 98 additions & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
#
# Lab 5 — QuickNotes in a Vagrant VM.
# Boots an Ubuntu 24.04 LTS VM, installs Go 1.24.x, builds QuickNotes from the
# synced ./app folder, and runs it as a systemd service on guest port 8080.
# The host reaches it on http://127.0.0.1:18080.

GO_VERSION = "1.24.5"

Vagrant.configure("2") do |config|
# Ubuntu 24.04 LTS. The bento box ships VirtualBox Guest Additions, which we
# need for the default (virtualbox) synced-folder type.
config.vm.box = "bento/ubuntu-24.04"

# Identify the VM clearly (shows up in the shell prompt and `vagrant ssh`).
config.vm.hostname = "quicknotes-vm"

# Forward host 18080 -> guest 8080, bound to loopback only so the app is not
# exposed to the local network.
config.vm.network "forwarded_port", guest: 8080, host: 18080, host_ip: "127.0.0.1"

# Mount the application source into the guest (default type: virtualbox).
config.vm.synced_folder "./app", "/opt/quicknotes/app"

# Cap resources at 2 vCPU / 1024 MB RAM (over-provisioning is an antipattern).
config.vm.provider "virtualbox" do |vb|
vb.name = "quicknotes-vm"
vb.memory = 1024
vb.cpus = 2
end

# Provisioning runs on first `vagrant up`; re-run with `vagrant provision`.
# The script is idempotent, so `vagrant up --provision` is safe to repeat.
config.vm.provision "shell", inline: <<-SHELL
#!/usr/bin/env bash
set -euo pipefail

GO_VERSION="#{GO_VERSION}"
case "$(uname -m)" in
x86_64)
GO_ARCH="amd64"
;;
aarch64|arm64)
GO_ARCH="arm64"
;;
*)
echo "Unsupported guest architecture: $(uname -m)" >&2
exit 1
;;
esac
GO_TARBALL="go${GO_VERSION}.linux-${GO_ARCH}.tar.gz"

export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y curl

# Install the pinned Go version only if it is not already present.
if ! /usr/local/go/bin/go version 2>/dev/null | grep -q "go${GO_VERSION} "; then
echo "Installing Go ${GO_VERSION}..."
curl -fsSL "https://go.dev/dl/${GO_TARBALL}" -o "/tmp/${GO_TARBALL}"
rm -rf /usr/local/go
tar -C /usr/local -xzf "/tmp/${GO_TARBALL}"
fi

# Make Go available on PATH for interactive logins (e.g. `vagrant ssh`).
echo 'export PATH=$PATH:/usr/local/go/bin' > /etc/profile.d/go.sh

# Build QuickNotes from the synced source into a stable location.
install -d /var/lib/quicknotes
/usr/local/go/bin/go build -C /opt/quicknotes/app -o /usr/local/bin/quicknotes .

# Run QuickNotes as a service so it survives reboots and starts on boot.
cat > /etc/systemd/system/quicknotes.service <<'UNIT'
[Unit]
Description=QuickNotes API
After=network-online.target
Wants=network-online.target

[Service]
Environment=ADDR=:8080
Environment=DATA_PATH=/var/lib/quicknotes/notes.json
Environment=SEED_PATH=/opt/quicknotes/app/seed.json
WorkingDirectory=/var/lib/quicknotes
ExecStart=/usr/local/bin/quicknotes
Restart=on-failure

[Install]
WantedBy=multi-user.target
UNIT

systemctl daemon-reload
systemctl enable quicknotes
systemctl restart quicknotes

echo "Provisioning done. QuickNotes should be live on guest :8080."
SHELL
end
Binary file added ansible/files/quicknotes
Binary file not shown.
2 changes: 2 additions & 0 deletions ansible/inventory.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[quicknotes_vm]
quicknotes-vm ansible_host=127.0.0.1 ansible_port=2222 ansible_user=vagrant ansible_ssh_private_key_file=.vagrant/machines/default/virtualbox/private_key ansible_python_interpreter=/usr/bin/python3 ansible_ssh_common_args='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -o PubkeyAcceptedKeyTypes=+ssh-rsa -o HostKeyAlgorithms=+ssh-rsa'
Loading