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
34 changes: 29 additions & 5 deletions .chezmoi.toml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,41 @@
{{- else -}}
{{- $personalGithubHostAlias = promptStringOnce . "gitPersonalGithubHostAlias" "Personal GitHub SSH host alias" "github-personal" -}}
{{- end -}}
{{- /* Reuse existing [data.codeberg] before prompting. The promptStringOnce
fallbacks below key off root names this template never writes back into
[data], so "Once" never engages; while origin was on Codeberg the
prompts were simply unreachable because inference always won. With
origin elsewhere, inference is empty and a configured machine would
re-prompt (and fail non-interactively) on every init. */ -}}
{{- $existingCodebergUser := "" -}}
{{- $existingCodebergHost := "" -}}
{{- $existingCodebergTokenOpRef := "" -}}
{{- $existingCodebergSshKeyOpRef := "" -}}
{{- if hasKey . "codeberg" -}}
{{- if hasKey .codeberg "user" -}}{{- $existingCodebergUser = .codeberg.user -}}{{- end -}}
{{- if hasKey .codeberg "host" -}}{{- $existingCodebergHost = .codeberg.host -}}{{- end -}}
{{- if hasKey .codeberg "tokenOpRef" -}}{{- $existingCodebergTokenOpRef = .codeberg.tokenOpRef -}}{{- end -}}
{{- if hasKey .codeberg "sshKeyOpRef" -}}{{- $existingCodebergSshKeyOpRef = .codeberg.sshKeyOpRef -}}{{- end -}}
{{- end -}}
{{- $existingCodebergIdentityFile := "" -}}
{{- if and (hasKey . "ssh") (hasKey .ssh "personal") (hasKey .ssh.personal "codebergIdentityFile") -}}
{{- $existingCodebergIdentityFile = .ssh.personal.codebergIdentityFile -}}
{{- end -}}
{{- $envPersonalCodebergUser := env "CHEZMOI_GIT_CODEBERG_USER" -}}
{{- $personalCodebergUser := "" -}}
{{- if ne $envPersonalCodebergUser "" -}}
{{- $personalCodebergUser = $envPersonalCodebergUser -}}
{{- else if ne $inferredPersonalCodebergUser "" -}}
{{- $personalCodebergUser = $inferredPersonalCodebergUser -}}
{{- else if ne $existingCodebergUser "" -}}
{{- $personalCodebergUser = $existingCodebergUser -}}
{{- else -}}
{{- $personalCodebergUser = promptStringOnce . "gitPersonalCodebergUser" "Codeberg username for repo routing" "codeberg-user" -}}
{{- end -}}
{{- $defaultCodebergHost := "codeberg.org" -}}
{{- if ne $inferredPersonalGhHost "" -}}
{{- if ne $existingCodebergHost "" -}}
{{- $defaultCodebergHost = $existingCodebergHost -}}
{{- else if ne $inferredPersonalGhHost "" -}}
{{- $defaultCodebergHost = $inferredPersonalGhHost -}}
{{- end -}}
[data]
Expand All @@ -96,14 +120,14 @@
tokenOpRef = "{{ if eq $profile "personal" }}{{ if ne (env "CHEZMOI_GH_TOKEN_OP_REF") "" }}{{ env "CHEZMOI_GH_TOKEN_OP_REF" }}{{ else }}{{ promptStringOnce . "ghTokenOpRefPersonal" "1Password ref for personal GitHub CLI token" "op://Private/GitHub CLI/token" }}{{ end }}{{ else }}{{ env "CHEZMOI_GH_TOKEN_OP_REF" }}{{ end }}"

[data.codeberg]
host = "{{ if ne (env "CHEZMOI_CODEBERG_HOST") "" }}{{ env "CHEZMOI_CODEBERG_HOST" }}{{ else }}{{ promptStringOnce . "codebergHost" "Codeberg hostname" $defaultCodebergHost }}{{ end }}"
host = "{{ if ne (env "CHEZMOI_CODEBERG_HOST") "" }}{{ env "CHEZMOI_CODEBERG_HOST" }}{{ else if ne $existingCodebergHost "" }}{{ $existingCodebergHost }}{{ else }}{{ promptStringOnce . "codebergHost" "Codeberg hostname" $defaultCodebergHost }}{{ end }}"
user = "{{ $personalCodebergUser }}"
tokenOpRef = "{{ if eq $profile "personal" }}{{ if ne (env "CHEZMOI_CODEBERG_TOKEN_OP_REF") "" }}{{ env "CHEZMOI_CODEBERG_TOKEN_OP_REF" }}{{ else }}{{ promptStringOnce . "codebergTokenOpRefPersonal" "1Password ref for Codeberg API token (fj)" "op://Private/Codeberg/token" }}{{ end }}{{ else }}{{ env "CHEZMOI_CODEBERG_TOKEN_OP_REF" }}{{ end }}"
sshKeyOpRef = "{{ if eq $profile "personal" }}{{ if ne (env "CHEZMOI_CODEBERG_SSH_KEY_OP_REF") "" }}{{ env "CHEZMOI_CODEBERG_SSH_KEY_OP_REF" }}{{ else }}{{ promptStringOnce . "codebergSshKeyOpRefPersonal" "1Password ref for Codeberg SSH private key" "op://Private/Codeberg SSH/private key" }}{{ end }}{{ else }}{{ env "CHEZMOI_CODEBERG_SSH_KEY_OP_REF" }}{{ end }}"
tokenOpRef = "{{ if eq $profile "personal" }}{{ if ne (env "CHEZMOI_CODEBERG_TOKEN_OP_REF") "" }}{{ env "CHEZMOI_CODEBERG_TOKEN_OP_REF" }}{{ else if ne $existingCodebergTokenOpRef "" }}{{ $existingCodebergTokenOpRef }}{{ else }}{{ promptStringOnce . "codebergTokenOpRefPersonal" "1Password ref for Codeberg API token (fj)" "op://Private/Codeberg/token" }}{{ end }}{{ else }}{{ env "CHEZMOI_CODEBERG_TOKEN_OP_REF" }}{{ end }}"
sshKeyOpRef = "{{ if eq $profile "personal" }}{{ if ne (env "CHEZMOI_CODEBERG_SSH_KEY_OP_REF") "" }}{{ env "CHEZMOI_CODEBERG_SSH_KEY_OP_REF" }}{{ else if ne $existingCodebergSshKeyOpRef "" }}{{ $existingCodebergSshKeyOpRef }}{{ else }}{{ promptStringOnce . "codebergSshKeyOpRefPersonal" "1Password ref for Codeberg SSH private key" "op://Private/Codeberg SSH/private key" }}{{ end }}{{ else }}{{ env "CHEZMOI_CODEBERG_SSH_KEY_OP_REF" }}{{ end }}"

[data.ssh.personal]
githubIdentityFile = "{{ env "CHEZMOI_SSH_PERSONAL_GITHUB_IDENTITY_FILE" }}"
codebergIdentityFile = "{{ if ne (env "CHEZMOI_SSH_PERSONAL_CODEBERG_IDENTITY_FILE") "" }}{{ env "CHEZMOI_SSH_PERSONAL_CODEBERG_IDENTITY_FILE" }}{{ else }}{{ promptStringOnce . "sshPersonalCodebergIdentityFile" "Path to personal Codeberg SSH private key" "~/.ssh/id_ed25519_codeberg" }}{{ end }}"
codebergIdentityFile = "{{ if ne (env "CHEZMOI_SSH_PERSONAL_CODEBERG_IDENTITY_FILE") "" }}{{ env "CHEZMOI_SSH_PERSONAL_CODEBERG_IDENTITY_FILE" }}{{ else if ne $existingCodebergIdentityFile "" }}{{ $existingCodebergIdentityFile }}{{ else }}{{ promptStringOnce . "sshPersonalCodebergIdentityFile" "Path to personal Codeberg SSH private key" "~/.ssh/id_ed25519_codeberg" }}{{ end }}"

[data.git.work]
name = "Jason Aguilon"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ on:

jobs:
pre-commit:
# Codeberg hosted runners do not serve ubuntu-latest; medium has the
# 10-minute runtime cap needed for an uncached mise toolchain install.
runs-on: codeberg-medium
runs-on: ubuntu-latest
env:
# CI/CD hardening — see dot_agents/skills/mise-security/SKILL.md
MISE_EXPERIMENTAL: "0"
Expand All @@ -21,9 +19,7 @@ jobs:
steps:
- uses: actions/checkout@v7

# Full URL: code.forgejo.org (the runner's default action source)
# does not mirror jdx/mise-action.
- uses: https://github.com/jdx/mise-action@v4
- uses: jdx/mise-action@v4
with:
install: true
cache: true
Expand Down
18 changes: 11 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ pre-commit hook setup** (`just repos::pre-commit-install`), and the recommended
`just repos::pre-commit-verify` check before pushes or PRs. Shell QA commands
are available via `just -f qa.just ...` after `mise install`.

Forgejo Actions runs pre-commit on PRs automatically (see
`.forgejo/workflows/pre-commit.yaml`); that does **not** install hooks on your
GitHub Actions runs pre-commit on PRs automatically (see
`.github/workflows/pre-commit.yaml`); that does **not** install hooks on your
computer until you run `just repos::pre-commit-install` once in the chezmoi
source directory.

Expand Down Expand Up @@ -340,9 +340,12 @@ scripts) use the same authenticated config as your shell:
- **personal** profile: `~/.config/gh-personal`
- **work** profile: `~/.config/gh`

The shell `gh` wrapper (`02-gh-wrapper.sh`) applies `gh-routes.d` and routes
`~/dev/repos/github.com/<user>/` (and chezmoi source while `origin` is still on
GitHub).
The shell `gh` wrapper (`02-gh-wrapper.sh`) applies `gh-routes.d`, then routes
automatically when your current directory is either:

- under `~/dev/repos/github.com/<user>/`, or
- inside your chezmoi source path (`chezmoi source-path`), whose `origin` is on
GitHub.

### Codeberg (`fj`)

Expand All @@ -351,8 +354,9 @@ Install [forgejo-cli](https://codeberg.org/forgejo-contrib/forgejo-cli)

`03-fj-default-config.sh` exports **`CHEZMOI_FJ_DATA_HOME`** (personal default
`~/.local/share/fj-personal`). The `fj()` wrapper (`04-fj-wrapper.sh`) sets
**`XDG_DATA_HOME`** there under `~/dev/repos/<codeberg-host>/<user>/` and in
chezmoi source when `origin` is on Codeberg. Agents should use the same prefix:
**`XDG_DATA_HOME`** there under `~/dev/repos/<codeberg-host>/<user>/`. The
chezmoi source is **not** routed to `fj` — its `origin` is on GitHub, so `gh`
owns it. Agents should use the same prefix:

```bash
XDG_DATA_HOME="${CHEZMOI_FJ_DATA_HOME:-$HOME/.local/share/fj-personal}" fj pr list
Expand Down
6 changes: 3 additions & 3 deletions docs/repo-maintenance.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ Boundary conventions:

## Pre-commit (markdown)

Forgejo Actions runs **[pre-commit](https://pre-commit.com)** on pull requests
and pushes to `master`/`main` via `.forgejo/workflows/pre-commit.yaml` (mise,
GitHub Actions runs **[pre-commit](https://pre-commit.com)** on pull requests
and pushes to `master`/`main` via `.github/workflows/pre-commit.yaml` (mise,
pre-commit cache, and Neovim headless tests). That job uses `mise exec --locked`
(same as local QA); it does **not** configure your machine.

Expand Down Expand Up @@ -144,7 +144,7 @@ just repos::pre-commit-verify # pre-commit run --all-files
```

Use this even when the local hook already passed. It gives you the same
repository-wide check that Forgejo Actions runs on the PR.
repository-wide check that GitHub Actions runs on the PR.

Re-run `just repos::pre-commit-install` after cloning on a new machine or if you
replace `.git/hooks`.
Expand Down
13 changes: 7 additions & 6 deletions dot_agents/skills/dotfiles-forgejo-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ name: dotfiles-forgejo-cli
description: >-
Use fj (forgejo-cli) for Codeberg and other Forgejo hosts in this chezmoi
setup. Use when creating or reviewing pull requests, issues, releases, or CI
on Codeberg, including the chezmoi source tree after migration from GitHub.
Prefer fj over gh for those hosts.
on Codeberg. Prefer fj over gh for those hosts.
---

# Forgejo CLI (fj) for Codeberg

When the task involves **Codeberg** (or another Forgejo host) or the **chezmoi
source** on a personal machine, use **`fj`**, not **`gh`**.
When the task involves **Codeberg** (or another Forgejo host), use **`fj`**, not
**`gh`**. The chezmoi source is **not** one of those hosts — its `origin` is on
GitHub, so use **`gh`** there (see **dotfiles-github-cli**).

## Use `fj` for

Expand Down Expand Up @@ -43,8 +43,9 @@ XDG_DATA_HOME="${CHEZMOI_FJ_DATA_HOME:-$HOME/.local/share/fj-personal}" \

## GitHub

For **`github.com`** remotes and `~/dev/repos/github.com/<user>/`, use **`gh`**
and the **dotfiles-github-cli** skill instead.
For **`github.com`** remotes, `~/dev/repos/github.com/<user>/`, and the
**chezmoi source** (`~/.local/share/chezmoi`, origin `aguil/dotfiles`), use
**`gh`** and the **dotfiles-github-cli** skill instead.

## Overlay routes

Expand Down
11 changes: 5 additions & 6 deletions dot_agents/skills/dotfiles-github-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,14 @@ GitHub.

For **Codeberg / Forgejo**, use **`fj`** (see **dotfiles-forgejo-cli** skill):
repo-scoped `fj()` sets `XDG_DATA_HOME` to `CHEZMOI_FJ_DATA_HOME` under
`~/dev/repos/<codeberg-host>/<user>/` and in the chezmoi source when `origin` is
on Codeberg. **`gh` does not support Forgejo hosts.**
`~/dev/repos/<codeberg-host>/<user>/`. **`gh` does not support Forgejo hosts.**

Typical split (adjust paths and hostnames to your layout):

| Role | Chezmoi source (example) | Use the `gh` login that owns this remote |
| ---------------------------- | ---------------------------------- | ----------------------------------------------- |
| Primary dotfiles | `~/.local/share/chezmoi` | `fj` if origin is Codeberg; else `gh` on GitHub |
| Secondary overlay (optional) | e.g. `~/.local/share/chezmoi-work` | Employer or second user on GitHub |
| Role | Chezmoi source (example) | Use the `gh` login that owns this remote |
| ---------------------------- | ---------------------------------- | ---------------------------------------- |
| Primary dotfiles | `~/.local/share/chezmoi` | `gh` on GitHub |
| Secondary overlay (optional) | e.g. `~/.local/share/chezmoi-work` | Employer or second user on GitHub |

## Fallback

Expand Down
10 changes: 5 additions & 5 deletions dot_agents/skills/mise-security/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ Commit updated lockfiles with the version bump.

## CI/CD hardening

| Action | Status here |
| -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Disable experimental features** — `MISE_EXPERIMENTAL=0` | Profile.d default; **Forgejo** `.forgejo/workflows/pre-commit.yaml` job `env` |
| **Paranoid + trust (CI)** — same posture as interactive shells, scoped to the checkout | Forgejo workflow: `MISE_PARANOID=1`, `MISE_TRUSTED_CONFIG_PATHS` = `${{ github.workspace }}`. No `MISE_CEILING_PATHS`: mise excludes the ceiling dir itself, so pointing it at the workspace hides the repo's own `.mise.toml`; paranoid mode already hard-fails on configs outside the trusted path |
| **Locked tool runs in CI** — `mise exec --locked` | Forgejo pre-commit + Neovim steps; `qa.just` / `.pre-commit-config.yaml` locally |
| Action | Status here |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Disable experimental features** — `MISE_EXPERIMENTAL=0` | Profile.d default; **GitHub Actions** `.github/workflows/pre-commit.yaml` job `env` |
| **Paranoid + trust (CI)** — same posture as interactive shells, scoped to the checkout | GitHub workflow: `MISE_PARANOID=1`, `MISE_TRUSTED_CONFIG_PATHS` = `${{ github.workspace }}`. No `MISE_CEILING_PATHS`: mise excludes the ceiling dir itself, so pointing it at the workspace hides the repo's own `.mise.toml`; paranoid mode already hard-fails on configs outside the trusted path |
| **Locked tool runs in CI** — `mise exec --locked` | GitHub pre-commit + Neovim steps; `qa.just` / `.pre-commit-config.yaml` locally |

In CI scripts that invoke mise, export the same vars (or the workspace-scoped
equivalents above on shared runners) and use `mise exec --locked`.
Expand Down
11 changes: 0 additions & 11 deletions dot_config/chezmoi/profile.d/04-fj-wrapper.sh.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ _chez_fj_route_data_home () {
}

fj () {
local chezmoi_source
local route_data_home
local fj_codeberg_host='{{ if hasKey . "codeberg" }}{{ .codeberg.host }}{{ else }}codeberg.org{{ end }}'
local fj_codeberg_repo_root="$HOME/dev/repos/$fj_codeberg_host/{{ if hasKey . "codeberg" }}{{ .codeberg.user }}{{ else }}{{ .git.personal.githubUser }}{{ end }}"
Expand All @@ -77,16 +76,6 @@ fj () {
return $?
;;
esac
if command -v chezmoi >/dev/null 2>&1; then
if chezmoi_source="$(chezmoi source-path 2>/dev/null)"; then
case "$PWD/" in
"$chezmoi_source"/*|"$chezmoi_source"/)
_chez_fj_run "$fj_data_home" "$@"
return $?
;;
esac
fi
fi
_chez_fj_run "$fj_data_home" "$@"
return $?
fi
Expand Down
2 changes: 0 additions & 2 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ if [ -z "$REPO_URL" ]; then
printf '%s\n' "Unable to determine dotfiles repo URL." >&2
printf '%s\n' "Set REPO_URL (or CHEZMOI_REPO_URL) and rerun." >&2
printf '%s\n' "Example SSH: REPO_URL='git@github.com:<user>/dotfiles.git' ./install.sh" >&2
printf '%s\n' "Example SSH: REPO_URL='git@codeberg.org:<user>/dotfiles.git' ./install.sh" >&2
printf '%s\n' "Example HTTPS: REPO_URL='https://github.com/<user>/dotfiles.git' ./install.sh" >&2
printf '%s\n' "Example HTTPS: REPO_URL='https://codeberg.org/<user>/dotfiles.git' ./install.sh" >&2
exit 1
fi

Expand Down
Loading