mirror of
https://github.com/outbackdingo/homelab-v.git
synced 2026-08-25 07:10:14 +00:00
feat(devcontainer): build a Devcontainer with useful tools for this project
Also use said devcontainer i GitHub workflows to validate config. * feat(devcontainer): build devcontainer Signed-off-by: Vegard Hagen <[email protected]> * feat(ci): validate tofu files on push Signed-off-by: Vegard Hagen <[email protected]> * feat(devcontainer): simplify devcontainer Signed-off-by: Vegard Hagen <[email protected]> * fix(devcontainer): don't cache package index This will reduce the final image size. Signed-off-by: Vegard Hagen <[email protected]> * feat(devcontainer): switch to ubuntu and use devcontainer features as much as possible Signed-off-by: Vegard Hagen <[email protected]> --------- Signed-off-by: Vegard Hagen <[email protected]>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
FROM docker.io/ubuntu:24.04
|
||||
@@ -0,0 +1,29 @@
|
||||
# Devcontainer
|
||||
|
||||
A container with all the necessary tools and then some used in this homelab.
|
||||
Check available features at [https://containers.dev/features](https://containers.dev/features),
|
||||
or edit the `Containerfile`.
|
||||
|
||||
**Disclaimer**: this is a fairly untested feature from the main author,
|
||||
feedback is welcome.
|
||||
|
||||
## Getting started
|
||||
|
||||
Find the appropriate guide for your IDE, e.g.
|
||||
|
||||
* [IDEA](https://www.jetbrains.com/help/idea/start-dev-container-inside-ide.html)
|
||||
* [VSCode](https://code.visualstudio.com/docs/devcontainers/containers)
|
||||
|
||||
Alternatively, you can start the devcontainer manually by running
|
||||
|
||||
```shell
|
||||
docker run -it --rm \
|
||||
--user $(id -u):$(id -g) \
|
||||
--name homelab-devcontainer \
|
||||
--mount target=/tmp,type=tmpfs \
|
||||
--mount type=bind,src=.,dst=/workspace \
|
||||
--workdir /workspace \
|
||||
ghcr.io/vehagn/homelab-devcontainer:latest
|
||||
```
|
||||
|
||||
from the project root.
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "Stonegarden Homelab Devcontainer",
|
||||
"build": {
|
||||
"dockerfile": "Containerfile",
|
||||
},
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/common-utils:2": {
|
||||
"installZsh": true,
|
||||
"configureZshAsDefaultShell": true,
|
||||
"installOhMyZsh": true,
|
||||
"installOhMyZshConfig": true,
|
||||
"upgradePackages": true,
|
||||
"username": "homelab"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/aws-cli:1": {},
|
||||
"ghcr.io/devcontainers/features/azure-cli:1": {},
|
||||
"ghcr.io/devcontainers/features/github-cli:1": {},
|
||||
"ghcr.io/devcontainers/features/git:1": {},
|
||||
"ghcr.io/devcontainers/features/go:1": {},
|
||||
"ghcr.io/devcontainers/features/java:1": {},
|
||||
"ghcr.io/devcontainers/features/python:1": {},
|
||||
"ghcr.io/devcontainers/features/hugo:1": {
|
||||
"extended": "true"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {},
|
||||
"ghcr.io/devcontainers-extra/features/argo-cd:1": {},
|
||||
"ghcr.io/devcontainers-extra/features/helmfile:1": {},
|
||||
"ghcr.io/devcontainers-extra/features/talosctl:1": {},
|
||||
"ghcr.io/devcontainers-extra/features/yamllint:2": {},
|
||||
"ghcr.io/dhoeric/features/k9s:1": {},
|
||||
"ghcr.io/dhoeric/features/google-cloud-cli:1": {
|
||||
"installGkeGcloudAuthPlugin": true
|
||||
},
|
||||
"ghcr.io/eitsupi/devcontainer-features/jq-likes": {
|
||||
"jqVersion": "latest",
|
||||
"yqVersion": "latest"
|
||||
},
|
||||
"ghcr.io/jungaretti/features/vim:1": {},
|
||||
"ghcr.io/robbert229/devcontainer-features/postgresql-client:1": {},
|
||||
"ghcr.io/robbert229/devcontainer-features/opentofu:1": {},
|
||||
"ghcr.io/schlich/devcontainer-features/powerlevel10k:1": {},
|
||||
"ghcr.io/skriptfabrik/devcontainer-features/hcloud-cli:1": {},
|
||||
"ghcr.io/skriptfabrik/devcontainer-features/infisical-cli:1.1.1": {},
|
||||
},
|
||||
"remoteUser": "homelab"
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
name: Build devcontainer
|
||||
|
||||
on:
|
||||
workflow_dispatch: { }
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths: [ ".devcontainer/**" ]
|
||||
schedule:
|
||||
- cron: "4 20 28 * *"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build devcontainer
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
|
||||
- name: Set up QEMU for multi-architecture builds
|
||||
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 #v3.6.0
|
||||
|
||||
- name: Setup Docker buildx for multi-architecture builds
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 #v3.11.1
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Pre-build dev container image
|
||||
uses: devcontainers/ci@8bf61b26e9c3a98f69cb6ce2f88d24ff59b785c6 #v0.3.1900000417
|
||||
with:
|
||||
platform: linux/amd64,linux/arm64
|
||||
imageName: ghcr.io/vehagn/homelab-devcontainer
|
||||
cacheFrom: ghcr.io/vehagn/homelab-devcontainer
|
||||
push: always
|
||||
@@ -1,92 +0,0 @@
|
||||
name: Validate tofu formatting on pull request
|
||||
|
||||
on:
|
||||
# Triggers the workflow on pull request events targeting the main or prod branches
|
||||
pull_request_target:
|
||||
branches:
|
||||
- main
|
||||
- prod
|
||||
# Also triggers on direct pull requests to main or prod (for forks or direct pushes)
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- prod
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
name: tofu fmt check
|
||||
runs-on: ubuntu-latest
|
||||
# Permissions needed for the job
|
||||
permissions:
|
||||
contents: read # To check out the code
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
with:
|
||||
# Fetch depth 2 is needed for comparing changes in PRs
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Get changed files
|
||||
id: changed_files # Assign an ID to refer to the outputs of this step
|
||||
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c # v46.0.5
|
||||
with:
|
||||
# Specify the output format for the list of files
|
||||
files_separator: " " # Use space as a separator for the loop below
|
||||
|
||||
- name: Setup OpenTofu
|
||||
uses: opentofu/setup-opentofu@592200bd4b9bbf4772ace78f887668b1aee8f716 # v1.0.5
|
||||
with:
|
||||
tofu_version: latest
|
||||
|
||||
- name: Validate tofu fmt (added/modified)
|
||||
run: |
|
||||
# Allow the script to continue even if tofu fmt fails for one file
|
||||
set +e
|
||||
|
||||
# Initialize check status (0 = success, 1 = failure)
|
||||
CHECK_STATUS=0
|
||||
echo "CHECK_STATUS=${CHECK_STATUS}" >> $GITHUB_ENV
|
||||
|
||||
echo "### Formatting Check for Changed Tofu Files" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
CHANGED_TOFU_FILES=""
|
||||
|
||||
# Loop through all files that were added or modified in the PR
|
||||
# Use the output from the 'tj-actions/changed-files' step
|
||||
for changed_file in ${{ steps.changed_files.outputs.all_changed_and_modified_files }}; do
|
||||
echo "Checking tofu fmt on ${changed_file}..."
|
||||
|
||||
# Check if the file has a .tofu or .tfvars extension
|
||||
if [[ $changed_file == *.tofu || $changed_file == *.tfvars ]]; then
|
||||
CHANGED_TOFU_FILES="$CHANGED_TOFU_FILES $changed_file"
|
||||
# Run tofu fmt in check mode. It exits with non-zero status if formatting is needed.
|
||||
tofu fmt -check $changed_file
|
||||
FMT_STATUS=$? # Capture the exit status of the tofu fmt command
|
||||
|
||||
# If tofu fmt failed (exit status is not 0)
|
||||
if [[ $FMT_STATUS -ne 0 ]]; then
|
||||
echo "- ❌ **${changed_file}** is not properly formatted. Please run \`tofu fmt\`." >> $GITHUB_STEP_SUMMARY
|
||||
# Update the overall check status to failure
|
||||
CHECK_STATUS=1
|
||||
echo "CHECK_STATUS=${CHECK_STATUS}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "- ✅ **${changed_file}** is properly formatted." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
else
|
||||
echo "Skipping non-tofu file: ${changed_file}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ -z "$CHANGED_TOFU_FILES" ]]; then
|
||||
echo "No changed or modified .tofu or .tfvars files found." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "Final check status: $CHECK_STATUS" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Exit the step with the final check status
|
||||
# If CHECK_STATUS is 1, the step (and job) will fail. If 0, it succeeds.
|
||||
echo "Final check status: $CHECK_STATUS"
|
||||
exit $CHECK_STATUS
|
||||
@@ -1,62 +0,0 @@
|
||||
name: Validate tofu formatting monthly
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Runs at 00:00 UTC on the first day of every month
|
||||
- cron: "0 0 1 * *"
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check_all:
|
||||
name: Check all tofu file formatting
|
||||
runs-on: ubuntu-latest
|
||||
# Permissions needed for the job
|
||||
permissions:
|
||||
contents: read # To check out the code
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
|
||||
- name: Setup OpenTofu
|
||||
uses: opentofu/setup-opentofu@592200bd4b9bbf4772ace78f887668b1aee8f716 # v1.0.5
|
||||
with:
|
||||
tofu_version: latest
|
||||
|
||||
- name: Validate tofu fmt for all files in tofu/ directory
|
||||
run: |
|
||||
# Allow the script to continue even if tofu fmt fails for one file
|
||||
set +e
|
||||
|
||||
# Initialize overall check status (0 = success, 1 = failure)
|
||||
CHECK_STATUS=0
|
||||
|
||||
echo "Searching for and checking .tofu and .tfvars files in the 'tofu/' directory recursively..."
|
||||
echo "### Tofu Format Check Results" >> $GITHUB_STEP_SUMMARY # Add a header to the summary
|
||||
|
||||
# Use find to locate files and pipe them safely to a while loop
|
||||
# This handles filenames with spaces or special characters correctly.
|
||||
find tofu/ -type f \( -name '*.tofu' -o -name '*.tfvars' \) -print0 | while IFS= read -r -d $'\0' file; do
|
||||
echo "Checking tofu fmt on ${file}..." # Log which file is being checked
|
||||
|
||||
# Run tofu fmt in check mode. It exits with non-zero status if formatting is needed.
|
||||
tofu fmt -check "${file}"
|
||||
FMT_STATUS=$?
|
||||
|
||||
# If tofu fmt failed (exit status is not 0)
|
||||
if [[ $FMT_STATUS -ne 0 ]]; then
|
||||
# Add a failure message to the GitHub Actions summary
|
||||
echo "❌ **${file}**: Needs formatting. Run \`tofu fmt\`." >> $GITHUB_STEP_SUMMARY
|
||||
# Update the overall check status to failure
|
||||
CHECK_STATUS=1
|
||||
else
|
||||
# Add a success message to the GitHub Actions summary
|
||||
echo "✅ **${file}**: Formatted correctly." >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
done
|
||||
|
||||
# Exit the step with the final check status
|
||||
# If CHECK_STATUS is 1, the step (and job) will fail. If 0, it succeeds.
|
||||
echo "Final check status: ${CHECK_STATUS}"
|
||||
exit ${CHECK_STATUS}
|
||||
@@ -0,0 +1,61 @@
|
||||
name: OpenTofu validation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '**' ]
|
||||
paths:
|
||||
- '**.tf'
|
||||
- '**.tofu'
|
||||
- '**.tfvars'
|
||||
- '**.tftpl'
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
pull_request_target:
|
||||
branches: [ main ]
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
validate-tofu:
|
||||
name: Validate
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
TOFU_DIR: tofu/kubernetes
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 #v3.4.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Tofu init
|
||||
uses: devcontainers/ci@8bf61b26e9c3a98f69cb6ce2f88d24ff59b785c6 #v0.3.1900000417
|
||||
with:
|
||||
imageName: ghcr.io/vehagn/homelab-devcontainer
|
||||
cacheFrom: ghcr.io/vehagn/homelab-devcontainer
|
||||
push: never
|
||||
runCmd: tofu -chdir=${{ env.TOFU_DIR }} init
|
||||
|
||||
- name: Tofu validate
|
||||
uses: devcontainers/ci@8bf61b26e9c3a98f69cb6ce2f88d24ff59b785c6 #v0.3.1900000417
|
||||
with:
|
||||
imageName: ghcr.io/vehagn/homelab-devcontainer
|
||||
cacheFrom: ghcr.io/vehagn/homelab-devcontainer
|
||||
push: never
|
||||
runCmd: tofu -chdir=${{ env.TOFU_DIR }} validate
|
||||
|
||||
- name: Tofu format
|
||||
uses: devcontainers/ci@8bf61b26e9c3a98f69cb6ce2f88d24ff59b785c6 #v0.3.1900000417
|
||||
with:
|
||||
imageName: ghcr.io/vehagn/homelab-devcontainer
|
||||
cacheFrom: ghcr.io/vehagn/homelab-devcontainer
|
||||
push: never
|
||||
runCmd: tofu -chdir=${{ env.TOFU_DIR }} fmt -recursive -diff -check
|
||||
@@ -0,0 +1,18 @@
|
||||
extends: default
|
||||
|
||||
yaml-files:
|
||||
- '*.yaml'
|
||||
- '*.yml'
|
||||
|
||||
ignore: |
|
||||
README.md
|
||||
LICENSE
|
||||
secret**.yaml
|
||||
|
||||
rules:
|
||||
document-start: { present: false }
|
||||
brackets:
|
||||
min-spaces-inside: 0
|
||||
max-spaces-inside: 10
|
||||
line-length:
|
||||
allow-non-breakable-inline-mappings: true
|
||||
@@ -26,7 +26,8 @@ Most of the services run on [Talos](https://www.talos.dev/) flavoured [Kubernete
|
||||
though I'm also running a [TrueNAS](https://www.truenas.com/) VM for storage
|
||||
and [Home Assistant](https://www.home-assistant.io/) VM for home automation.
|
||||
|
||||
To organise all the configuration I've opted for an approach using Kustomized Helm
|
||||
To organise all the configuration,
|
||||
I've opted for an approach using Kustomized Helm
|
||||
with [Argo CD](https://argoproj.github.io/cd/) which I've explained in more
|
||||
detail [in this article](https://blog.stonegarden.dev/articles/2023/09/argocd-kustomize-with-helm/).
|
||||
|
||||
@@ -34,9 +35,9 @@ I journal my homelab journey over at my self-hosted [blog](https://blog.stonegar
|
||||
|
||||
## 🧑💻 Getting Started
|
||||
|
||||
If you're new to Kubernetes I've written a fairly thorough guide
|
||||
If you're new to Kubernetes, I've written a fairly thorough guide
|
||||
on [Bootstrapping k3s with Cilium](https://blog.stonegarden.dev/articles/2024/02/bootstrapping-k3s-with-cilium/).
|
||||
In the article I try to guide you from a fresh Debian 12 Bookworm install to a working cluster using
|
||||
In the article I try to guide you from a fresh Debian 12 Bookworm installation to a working cluster using
|
||||
the [k3s](https://k3s.io) flavour of Kubernetes with [Cilium](https://cilium.io) as a [CNI](https://www.cni.dev)
|
||||
and [IngressController](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/).
|
||||
|
||||
@@ -47,6 +48,12 @@ is more your thing.
|
||||
The current iteration of my homelab runs on [Talos](https://talos.dev) Kubernetes and is set up according
|
||||
to [this article](https://blog.stonegarden.dev/articles/2024/08/talos-proxmox-tofu/).
|
||||
|
||||
## 🏃 Devcontainer
|
||||
|
||||
A [devcontainer](https://containers.dev/) containing the required tools is available for this repository
|
||||
as [ghcr.io/vehagn/homelab-devcontainer](https://github.com/vehagn/homelab/pkgs/container/homelab-devcontainer).
|
||||
See [./devcontainer](./.devcontainer) for details.
|
||||
|
||||
## ⚙️ Core Components
|
||||
|
||||
* [Proxmox VE](https://www.proxmox.com/en/proxmox-virtual-environment): Server management and KVM hypervisor.
|
||||
|
||||
+7
-5
@@ -66,12 +66,14 @@
|
||||
"matchDepTypes": [
|
||||
"provider",
|
||||
"required_provider"
|
||||
]
|
||||
},
|
||||
{
|
||||
"matchManagers": [
|
||||
"github-actions"
|
||||
],
|
||||
"matchUpdateTypes": [
|
||||
"minor",
|
||||
"patch"
|
||||
],
|
||||
"automerge": true
|
||||
"groupName": "GitHub Actions",
|
||||
"groupSlug": "github-actions"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user