diff --git a/.chezmoi.toml.tmpl b/.chezmoi.toml.tmpl index eb61d81..39c4312 100644 --- a/.chezmoi.toml.tmpl +++ b/.chezmoi.toml.tmpl @@ -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] @@ -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" diff --git a/.forgejo/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml similarity index 75% rename from .forgejo/workflows/pre-commit.yaml rename to .github/workflows/pre-commit.yaml index a832260..037d8d0 100644 --- a/.forgejo/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -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" @@ -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 diff --git a/README.md b/README.md index bf93f15..438b91e 100644 --- a/README.md +++ b/README.md @@ -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. @@ -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//` (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//`, or +- inside your chezmoi source path (`chezmoi source-path`), whose `origin` is on + GitHub. ### Codeberg (`fj`) @@ -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///` and in -chezmoi source when `origin` is on Codeberg. Agents should use the same prefix: +**`XDG_DATA_HOME`** there under `~/dev/repos///`. 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 diff --git a/docs/repo-maintenance.md b/docs/repo-maintenance.md index a99f807..7a452c2 100644 --- a/docs/repo-maintenance.md +++ b/docs/repo-maintenance.md @@ -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. @@ -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`. diff --git a/dot_agents/skills/dotfiles-forgejo-cli/SKILL.md b/dot_agents/skills/dotfiles-forgejo-cli/SKILL.md index e192889..4040c67 100644 --- a/dot_agents/skills/dotfiles-forgejo-cli/SKILL.md +++ b/dot_agents/skills/dotfiles-forgejo-cli/SKILL.md @@ -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 @@ -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//`, use **`gh`** -and the **dotfiles-github-cli** skill instead. +For **`github.com`** remotes, `~/dev/repos/github.com//`, and the +**chezmoi source** (`~/.local/share/chezmoi`, origin `aguil/dotfiles`), use +**`gh`** and the **dotfiles-github-cli** skill instead. ## Overlay routes diff --git a/dot_agents/skills/dotfiles-github-cli/SKILL.md b/dot_agents/skills/dotfiles-github-cli/SKILL.md index 5b04171..6549b62 100644 --- a/dot_agents/skills/dotfiles-github-cli/SKILL.md +++ b/dot_agents/skills/dotfiles-github-cli/SKILL.md @@ -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///` and in the chezmoi source when `origin` is -on Codeberg. **`gh` does not support Forgejo hosts.** +`~/dev/repos///`. **`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 diff --git a/dot_agents/skills/mise-security/SKILL.md b/dot_agents/skills/mise-security/SKILL.md index 90f4c4d..1363c67 100644 --- a/dot_agents/skills/mise-security/SKILL.md +++ b/dot_agents/skills/mise-security/SKILL.md @@ -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`. diff --git a/dot_config/chezmoi/profile.d/04-fj-wrapper.sh.tmpl b/dot_config/chezmoi/profile.d/04-fj-wrapper.sh.tmpl index e9002d7..3e3e039 100644 --- a/dot_config/chezmoi/profile.d/04-fj-wrapper.sh.tmpl +++ b/dot_config/chezmoi/profile.d/04-fj-wrapper.sh.tmpl @@ -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 }}" @@ -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 diff --git a/install.sh b/install.sh index 64d35e3..ea615bb 100755 --- a/install.sh +++ b/install.sh @@ -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:/dotfiles.git' ./install.sh" >&2 - printf '%s\n' "Example SSH: REPO_URL='git@codeberg.org:/dotfiles.git' ./install.sh" >&2 printf '%s\n' "Example HTTPS: REPO_URL='https://github.com//dotfiles.git' ./install.sh" >&2 - printf '%s\n' "Example HTTPS: REPO_URL='https://codeberg.org//dotfiles.git' ./install.sh" >&2 exit 1 fi