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
3 changes: 3 additions & 0 deletions .chezmoiignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ docs/
README.md
install_*
.gitattributes
Makefile
tools.env
ci/
{{ if ne .chezmoi.os "windows" }}
AppData/
Documents/WindowsPowerShell/Profile.ps1
Expand Down
60 changes: 60 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# The same check a workstation runs (`make check`), on the two operating
# systems the templates branch on (ADR-0017, ci.mirrors-the-local-check).
# A red step here is the Makefile target to run at home.
name: CI

on:
push:
branches: [main]
pull_request:

# The default token in a public repository may carry write; nothing here
# needs more than a read.
permissions:
contents: read

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

jobs:
check:
name: check
runs-on: ${{ matrix.os }}
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
steps:
# Pinned by commit, the tag in the comment (toolchain.tools-pinned-with-it).
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v7.0.1

# The private terms, from the repository secret, into a file outside the
# workspace. Through `env:`, never in the script text. Required wherever
# the secret should exist — a push, or a pull request from this
# repository; a fork's pull request has no secret and the check says
# so loudly and passes, as on a machine not set up yet.
- name: private terms
env:
PRIVATE_TERMS: ${{ secrets.PRIVATE_TERMS }}
FROM_THIS_REPOSITORY: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
run: |
if [ -n "$PRIVATE_TERMS" ]; then
printf '%s\n' "$PRIVATE_TERMS" > "$RUNNER_TEMP/private-terms"
echo "PRIVATE_TERMS_FILE=$RUNNER_TEMP/private-terms" >> "$GITHUB_ENV"
fi
if [ "$FROM_THIS_REPOSITORY" = "true" ]; then
echo "PRIVATE_REFS_REQUIRE_TERMS=1" >> "$GITHUB_ENV"
fi

# The four targets `make check` runs, one step each, so a red step is
# the target to run at home.
- name: make tools
run: make tools
- name: make render
run: make render
- name: make lint
run: make lint
- name: make private-refs
run: make private-refs
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Pinned tools `make tools` downloads (tools.env). A dot-file at the source
# root is not a chezmoi target, so nothing here is deployed.
.tools/
30 changes: 30 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# The one check target (ADR-0017, ci.mirrors-the-local-check): what a
# workstation runs is what .github/workflows/ci.yaml runs, step for step.
# Each target is its own script under scripts/, so a red job names its step
# and the scripts are themselves under `make lint`.

.POSIX:

check: tools render lint private-refs
@echo " ok tools render lint private-refs" >&2

# Pinned tools into .tools/ (tools.env); never the machine's.
tools:
@sh scripts/tools.sh

# Every template renders against placeholder data, hermetically.
render: tools
@sh scripts/render.sh

# shellcheck over every tracked shell script.
lint: tools
@sh scripts/lint.sh

# No private identifier in any tracked plaintext file.
private-refs:
@sh scripts/check-private-refs.sh --tree

clean:
@rm -rf .tools

.PHONY: check tools render lint private-refs clean
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
# Dotfiles

[![CI](https://github.com/fredericrous/dotfiles/actions/workflows/ci.yaml/badge.svg)](https://github.com/fredericrous/dotfiles/actions/workflows/ci.yaml)

personal environment files

## Checks

`make check` is what CI runs, with the same commands and the same pinned
tools (`tools.env`, installed into `.tools/`): every template renders
against placeholder data, the shell scripts pass shellcheck, and no tracked
plaintext file names private infrastructure. The private terms live outside
the tree (`~/.config/chezmoi/private-terms`) and, for CI, in the
`PRIVATE_TERMS` repository secret — a copy: whoever edits the file re-sets
the secret with `gh secret set PRIVATE_TERMS < ~/.config/chezmoi/private-terms`.

## Requirements

import your gpg keys
Expand Down
2 changes: 2 additions & 0 deletions amont.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
#
# stage name scope severity command
pre-commit private-refs * block scripts/check-private-refs.sh
# What CI runs, before the remote sees the push (ADR-0017). Warm: ~10 s.
pre-push check * block make check
15 changes: 15 additions & 0 deletions ci/chezmoi.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# The configuration `make render` runs chezmoi with: placeholder data for the
# five keys the templates read, none of them a real value. The real values
# live in ~/.config/chezmoi/chezmoi.toml on a workstation, generated by
# .chezmoi.toml.tmpl at `chezmoi init` and never committed.

[data]
bwserver = ""

[data.forge]
host = "forge.example.invalid"
slug = "example"

[data.work]
dir = ""
config = ""
Loading
Loading