Skip to content
Merged
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
78 changes: 74 additions & 4 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ jobs:
printf '%s' "$OCI_API_KEY_PEM" > ~/.oci/oci_api_key.pem
chmod 600 ~/.oci/oci_api_key.pem
cat > ~/.oci/config <<EOF
[syscode-homelab]
[DEFAULT]
user=$OCI_USER_OCID
fingerprint=$OCI_FINGERPRINT
tenancy=$OCI_TENANCY_OCID
region=uk-london-1
region=$OCI_REGION
key_file=$HOME/.oci/oci_api_key.pem
EOF
chmod 600 ~/.oci/config
Expand All @@ -62,12 +62,78 @@ jobs:
OCI_FINGERPRINT: ${{ secrets.OCI_FINGERPRINT }}
OCI_TENANCY_OCID: ${{ secrets.OCI_TENANCY_OCID }}
OCI_API_KEY_PEM: ${{ secrets.OCI_API_KEY_PEM }}
OCI_REGION: ${{ secrets.OCI_REGION }}

- name: Write backend config
run: printf '%s' "$TF_BACKEND_CONFIG" > tofu/oci/backend-config.tfvars
env:
TF_BACKEND_CONFIG: ${{ secrets.TF_BACKEND_CONFIG }}

- name: Install OCI CLI
run: pip install oci-cli --quiet

- name: Check free tier capacity
env:
OCI_COMPARTMENT_OCID: ${{ secrets.OCI_COMPARTMENT_OCID }}
run: |
echo "Querying live OCI state for compartment ${OCI_COMPARTMENT_OCID}"

INSTANCES=$(oci compute instance list \
--compartment-id "$OCI_COMPARTMENT_OCID" \
--all --output json 2>/dev/null || echo '{"data":[]}')

LIVE_STATES='.["lifecycle-state"] != "TERMINATING" and .["lifecycle-state"] != "TERMINATED"'
A1_FILTER="select(.shape==\"VM.Standard.A1.Flex\") | select($LIVE_STATES)"
MICRO_FILTER="select(.shape==\"VM.Standard.E2.1.Micro\") | select($LIVE_STATES)"

CURRENT_OCPUS=$(echo "$INSTANCES" | \
jq "[.data[] | $A1_FILTER | (.\"shape-config\".ocpus // 0)] | add // 0")
CURRENT_RAM=$(echo "$INSTANCES" | \
jq "[.data[] | $A1_FILTER | (.\"shape-config\".\"memory-in-gbs\" // 0)] | add // 0")
CURRENT_MICRO=$(echo "$INSTANCES" | \
jq "[.data[] | $MICRO_FILTER] | length")

REQUESTED_OCPUS=$(grep -oE 'ocpus\s*=\s*[0-9]+' tofu/oci/terraform.tfvars \
| awk -F'=' '{s+=int($2)} END {print s+0}')
REQUESTED_RAM=$(grep -oE 'memory_gb\s*=\s*[0-9]+' tofu/oci/terraform.tfvars \
| awk -F'=' '{s+=int($2)} END {print s+0}')
REQUESTED_MICRO=$(grep -c 'micro_nodes' tofu/oci/terraform.tfvars || echo 0)

MAX_AMPERE_OCPUS=4
MAX_AMPERE_RAM_GB=24
MAX_MICRO_INSTANCES=1

echo "A1 live: ${CURRENT_OCPUS}/${MAX_AMPERE_OCPUS} OCPU, ${CURRENT_RAM}/${MAX_AMPERE_RAM_GB} GB"
echo "A1 tfvars: ${REQUESTED_OCPUS} OCPU, ${REQUESTED_RAM} GB"
echo "Micro: live=${CURRENT_MICRO}, tfvars=${REQUESTED_MICRO}, limit=${MAX_MICRO_INSTANCES}"

FAIL=0
if [ "$(echo "$REQUESTED_OCPUS > $MAX_AMPERE_OCPUS" | bc)" = "1" ]; then
echo "ERROR: tfvars requests ${REQUESTED_OCPUS} A1 OCPU but limit is ${MAX_AMPERE_OCPUS}"
FAIL=1
fi
if [ "$(echo "$CURRENT_OCPUS > $MAX_AMPERE_OCPUS" | bc)" = "1" ]; then
echo "ERROR: live A1 OCPU=${CURRENT_OCPUS} already exceeds limit=${MAX_AMPERE_OCPUS} — drift detected"
FAIL=1
fi
if [ "$(echo "$REQUESTED_RAM > $MAX_AMPERE_RAM_GB" | bc)" = "1" ]; then
echo "ERROR: tfvars requests ${REQUESTED_RAM} GB A1 RAM but limit is ${MAX_AMPERE_RAM_GB} GB"
FAIL=1
fi
if [ "$(echo "$CURRENT_RAM > $MAX_AMPERE_RAM_GB" | bc)" = "1" ]; then
echo "ERROR: live A1 RAM=${CURRENT_RAM} GB already exceeds limit=${MAX_AMPERE_RAM_GB} GB — drift detected"
FAIL=1
fi
if [ "$REQUESTED_MICRO" -gt "$MAX_MICRO_INSTANCES" ]; then
echo "ERROR: tfvars requests ${REQUESTED_MICRO} Micro but limit is ${MAX_MICRO_INSTANCES}"
FAIL=1
fi
if [ "$CURRENT_MICRO" -gt "$MAX_MICRO_INSTANCES" ]; then
echo "ERROR: live Micro=${CURRENT_MICRO} exceeds limit=${MAX_MICRO_INSTANCES} — drift"
FAIL=1
fi
exit $FAIL

- name: Setup OpenTofu
uses: opentofu/setup-opentofu@v2.0.0
with:
Expand All @@ -86,13 +152,16 @@ jobs:
-var="compartment_ocid=$OCI_COMPARTMENT_OCID" \
-var="talos_image_ocid=${{ steps.talos_image.outputs.ocid }}" \
-var="omni_join_token=$OMNI_JOIN_TOKEN" \
-var="omni_endpoint=$OMNI_ENDPOINT" \
-var="tailscale_auth_key=$TAILSCALE_AUTH_KEY" \
-var="oci_config_profile=DEFAULT" \
-var-file=terraform.tfvars \
-out=tfplan
env:
OCI_TENANCY_OCID: ${{ secrets.OCI_TENANCY_OCID }}
OCI_COMPARTMENT_OCID: ${{ secrets.OCI_COMPARTMENT_OCID }}
OMNI_JOIN_TOKEN: ${{ secrets.OMNI_JOIN_TOKEN }}
OMNI_ENDPOINT: ${{ secrets.OMNI_ENDPOINT }}
TAILSCALE_AUTH_KEY: ${{ secrets.TAILSCALE_AUTH_KEY }}
TF_LOG: WARN

Expand Down Expand Up @@ -120,11 +189,11 @@ jobs:
printf '%s' "$OCI_API_KEY_PEM" > ~/.oci/oci_api_key.pem
chmod 600 ~/.oci/oci_api_key.pem
cat > ~/.oci/config <<EOF
[syscode-homelab]
[DEFAULT]
user=$OCI_USER_OCID
fingerprint=$OCI_FINGERPRINT
tenancy=$OCI_TENANCY_OCID
region=uk-london-1
region=$OCI_REGION
key_file=$HOME/.oci/oci_api_key.pem
EOF
chmod 600 ~/.oci/config
Expand All @@ -133,6 +202,7 @@ jobs:
OCI_FINGERPRINT: ${{ secrets.OCI_FINGERPRINT }}
OCI_TENANCY_OCID: ${{ secrets.OCI_TENANCY_OCID }}
OCI_API_KEY_PEM: ${{ secrets.OCI_API_KEY_PEM }}
OCI_REGION: ${{ secrets.OCI_REGION }}

- name: Write backend config
run: printf '%s' "$TF_BACKEND_CONFIG" > tofu/oci/backend-config.tfvars
Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ flake.lock
.dagger/
dagger/__pycache__/

# AI tooling
.specstory/
docs/plans/
.claude/

# Artifacts
artifacts/
*.qcow2
Expand Down
6 changes: 6 additions & 0 deletions .markdownlintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Superseded aspirational/exploratory docs with pre-existing violations
docs/nix-dagger-analysis.md
docs/nix-dagger-detailed.md
docs/OCI_AMPERE_BUILD.md
# Legacy reference plan (Proxmox+Ceph phase, abandoned) — pre-existing violations
PLAN.md
16 changes: 13 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ See [DEVELOPMENT.md](DEVELOPMENT.md) for detailed setup instructions.

We use [Conventional Commits](https://www.conventionalcommits.org/):

```
```text
<type>(<scope>): <subject>

<body>
Expand All @@ -33,6 +33,7 @@ We use [Conventional Commits](https://www.conventionalcommits.org/):
```

**Types:**

- `feat`: New feature
- `fix`: Bug fix
- `docs`: Documentation only
Expand All @@ -43,7 +44,8 @@ We use [Conventional Commits](https://www.conventionalcommits.org/):
- `chore`: Changes to build process or auxiliary tools

**Examples:**
```

```text
feat(tofu): add Proxmox provider configuration

docs: update README with devbox instructions
Expand All @@ -56,16 +58,19 @@ fix(check_availability): handle OCI API timeout errors
Before committing, ensure:

1. **Code is formatted:**

```bash
devbox run fmt
```

2. **Linters pass:**

```bash
devbox run lint
```

3. **Pre-commit hooks pass:**

```bash
pre-commit run --all-files
```
Expand All @@ -83,7 +88,7 @@ Before committing, ensure:
- Follow PEP 8 (enforced by Black + Flake8)
- Add docstrings to functions
- Use type hints where beneficial
- Maximum line length: 100 characters
- Maximum line length: 120 characters

### Documentation

Expand All @@ -97,6 +102,7 @@ Before committing, ensure:
1. **Fork the repository**

2. **Create a feature branch:**

```bash
git checkout -b feat/your-feature-name
```
Expand All @@ -107,18 +113,21 @@ Before committing, ensure:
- Add/update tests if applicable

4. **Test locally:**

```bash
devbox run lint
devbox run check # Validate OpenTofu
```

5. **Commit with conventional commits:**

```bash
git add .
git commit -m "feat: add new feature"
```

6. **Push to your fork:**

```bash
git push origin feat/your-feature-name
```
Expand All @@ -141,6 +150,7 @@ Before committing, ensure:
### Larger Contributions

Please open an issue first to discuss:

- New features
- Architecture changes
- Breaking changes
Expand Down
Loading
Loading