Mac build agent — Salt managed with observability #174
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/pal-e-platform#174
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Feature
Lineage
project-pal-e-platform→ Board item. Supersedes manual Mac setup from #166.Repo
forgejo_admin/pal-e-platformUser Story
As Lucas
I want the Mac build agent managed by Salt with logs and metrics in Grafana
So that the Mac is reproducible infrastructure, not a manually configured laptop
Context
The Mac (lucass-macbook-air-1) is now a CI build machine for iOS builds. Current setup was done manually via SSH — fragile, not reproducible, no observability. This ticket brings it under Salt management with full observability.
Three sub-deliverables:
File Targets
Files to create:
salt/states/mac-agent/init.sls— orchestratorsalt/states/mac-agent/woodpecker.sls— agent binary + launchd plistsalt/states/mac-agent/observability.sls— promtail + node-exporter launchd servicessalt/states/mac-agent/homebrew.sls— managed packages (node, fastlane)salt/states/mac-agent/magicdns.sls— verify Tailscale MagicDNS configsalt/pillar/mac-agent/init.sls— secrets (agent token, Loki URL)Files to modify:
salt/pillar/top.sls— add Mac minion targetingterraform/main.tf— Prometheus scrape config for Mac node-exporter (Tailscale IP)Files NOT to touch:
Acceptance Criteria
salt 'lucass-macbook-air-1' state.apply mac-agentprovisions everythingTest Expectations
salt 'lucass-macbook-air-1' test.pingreturns Truesalt 'lucass-macbook-air-1' state.apply mac-agent test=Trueshows no errors{host="lucass-macbook-air-1"}returns agent logsup{instance=~".*macbook.*"}returns 1Constraints
brew install salt-miniononceChecklist
test=TrueRelated
project-capacitor-mobile— consumer of the Mac build agentTicket Scope Review: #174
TEMPLATE COMPLIANCE (template-issue)
The issue follows the
template-issueformat closely. Section-by-section:### Type### Lineageproject-pal-e-platformand supersedes #166. Path 2 (board-driven), so no plan phase ancestry required.### Repoforgejo_admin/pal-e-platform### User Story### Context### File Targets### Acceptance Criteria### Test Expectations### Constraintsbrew installdependency.### Checklist### Relatedproject-capacitor-mobile.Assessment: Passes template compliance.
TRACEABILITY TRIANGLE
story:superuser-deploytofu plan/applyand see them succeed in Woodpecker CI without manual intervention."arch:ci-pipelinearch:ci-pipeline= Woodpecker CItype:infraThe
arch:ci-pipelinelabel is a reasonable fit. The work touches Woodpecker agent infrastructure, which is the CI pipeline's execution layer. The Salt and observability aspects are enablers of the CI pipeline, not separate architecture components.Assessment: Triangle traces correctly.
FILE TARGET SPECIFICITY
File targets are specific enough for agent execution:
salt/states/mac-agent/andsalt/pillar/mac-agent/-- follows the existing Salt directory convention (verified:salt/states/haskernel/,k3s/,nvidia/,packages/, etc. withinit.slspattern).salt/pillar/top.sls(currently only targetsarchbox-- agent will addlucass-macbook-air-1targeting),terraform/main.tf(Prometheus scrape config).One gap: The "Grafana -- dashboard for Mac agent build metrics" file target is vague. Existing dashboards follow the pattern
terraform/dashboards/{name}.json+ akubernetes_config_map_v1resource inmain.tf. The agent can discover this pattern from context (3 existing dashboards follow it), but specifying the exact path (terraform/dashboards/mac-agent-dashboard.json) would remove ambiguity.ACCEPTANCE CRITERIA TESTABILITY
All 7 criteria are testable:
salt 'lucass-macbook-air-1' test.pingstate.apply mac-agentprovisions everything -- verifiable via SaltdigornslookupAssessment: All criteria are testable with specific verification methods.
DEPENDENCIES
project-capacitor-mobilebrew install salt-minionAssessment: Dependencies are documented and correct. The constraint about needing Lucas for the initial Salt install is honest and important.
MINOR OBSERVATIONS (non-blocking)
Missing
track:devopslabel on the board item. This is devops infrastructure work. Per template-ticket: "Not every ticket needs every label" -- so not required, but would improve filtering.Missing
scope:label. This work originated from superseding #166 (manual setup).scope:plannedor no scope label are both acceptable.Related section references
project-capacitor-mobile(consumer) but does not explicitly referenceproject-pal-e-platform(the project this ticket belongs to). The Lineage section covers this, so it is traceable, but adding it to Related would be consistent withtemplate-issueguidance ("project-slug -- project this affects").Grafana dashboard file target should be more specific: suggest
terraform/dashboards/mac-agent-dashboard.jsonto match existing convention.No points assigned on the board item. Per template-ticket, points should be assigned during triage. This is a multi-file, multi-tool ticket (Salt + Terraform + Grafana) -- likely a 5 or 8.
SOP COMPLIANCE
VERDICT: APPROVED
Ticket is well-scoped and agent-executable. The four minor observations above (track label, scope label, Grafana path specificity, points) are quality-of-life improvements, not blockers. An agent can execute this ticket as written.
Progress Update (2026-03-26) — Salt minion connected
Completed
master: 100.110.151.59,id: lucass-macbook-air-1salt-key -a lucass-macbook-air-1salt 'lucass-macbook-air-1' test.pingreturns TrueInfrastructure fixes discovered and applied
Salt master interface binding — was
127.0.0.1(localhost only), changed to100.110.151.59(Tailscale IP). Comment in config predicted this: "When scaling to multi-node, change this to the Tailscale IP."nftables stale interface index bug — firewall rule
iif 5was stale (Tailscale was index 5 at boot, now index 87 after restarts). Reloaded/etc/nftables.confto getiif "tailscale0"(name-based). Root cause: nftables resolves interface names to numeric indexes at load time. Need a systemd dependency or timer to reload after Tailscale starts. Discovered scope.Local archbox minion — updated from
master: 127.0.0.1tomaster: 100.110.151.59to match master's new bind address.Woodpecker agent connection issue
woodpecker.tail5b443a.ts.net:9000) directly over Tailscale, not through a funnelWOODPECKER_SERVER=woodpecker.tail5b443a.ts.net:9000,WOODPECKER_GRPC_SECURE=falseKey lessons
Remaining
Scope Review: BLOCK (Phase 30 review)
Review note:
review-287-2026-03-27Phase 30 (Mac CI Agent) is well-scoped but hard-blocked by Apple Developer Program enrollment. Board item #287 correctly carries the
blocked-by:apple-dev-enrollmentlabel.Key issues:
salt/states/mac-agent/andsalt/pillar/mac-agent.slsalready exist in the repo. The phase note should incorporate Salt config management.arch:ci-pipelinefor consistency with other CI items.