Installs into .claude/skills of the current project.
Are you the author of Gen Forgejo Dir?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/sgaunet-gen-forgejo-dir)
---
name: gen-forgejo-dir
description: Generate complete .forgejo/workflows directory with Forgejo Actions workflows (test, lint, release) for Go projects
argument-hint: "[--force] [--minimal] [--dry-run]"
user-invocable: true
disable-model-invocation: true
allowed-tools: Read, Write, Bash(git:*), Bash(test:*), Bash(fgj:*), AskUserQuestion
---
# Generate .forgejo Directory
Instantly create a complete `.forgejo/workflows` directory structure for Go projects with production-ready, **mise-based** Forgejo Actions workflows (linting, coverage, snapshot builds, releases).
Forgejo Actions reuses **GitHub-Actions-compatible workflow syntax**, so the workflow content is identical to what `/gen-github-dir` produces. The key differences are the directory location (`.forgejo/workflows/` instead of `.github/workflows/`), the `runs-on` runner label, and the action/registry source assumptions described below.
Like the GitHub variant, the workflows install tooling via `jdx/mise-action@v3` and run `task …`, so CI uses the exact tool versions pinned in `mise.toml` (created at the repo root if missing). This also **shrinks the set of GitHub actions that must be mirrored** on your instance to just `actions/checkout` and `jdx/mise-action`.
## Why This Skill Exists
**Problem**: Setting up CI/CD for Go projects on a Forgejo instance requires manually creating multiple workflow files, understanding that Forgejo Actions mirrors GitHub Actions syntax but lives under a different directory, and wiring up runner labels - a 30-60 minute process.
**Solution**: One-command generation that:
- Creates a complete `.forgejo/workflows` directory structure
- Includes comprehensive workflows: linting, coverage, snapshot builds, releases
- Targets a Forgejo Actions runner label (not `ubuntu-latest`)
- Preserves all customization comments for user control
## Forgejo Actions Assumptions
This skill makes the following assumptions about your Forgejo instance. Review them before running:
1. **Runner label** — Workflows are generated with `runs-on: docker` (a common default label for the official Forgejo Actions runner). You must have at least one registered Forgejo Actions runner that advertises this label. Manage runners with the Forgejo CLI:
```bash
fgj actions runner list # List registered runners and their labels
fgj actions runner register # Register a new runner
```
If your runner uses a different label (e.g. `self-hosted`, `ubuntu-latest`, or a custom label), edit `runs-on:` in the generated files or re-run after adjusting your runner registration. Without a matching registered runner, workflows will queue forever.
2. **Action source / GitHub mirror** — Because tooling is installed via mise, the workflows only reference **two** GitHub actions: `actions/checkout` and `jdx/mise-action`. Forgejo pulls actions from a **configurable registry**; on instances configured with a GitHub Actions proxy/mirror (the common default, e.g. `https://data.forgejo.org` or a `code.forgejo.org` mirror), these references resolve transparently. If your instance is not configured to mirror GitHub actions, replace these two `uses:` references with mirrored equivalents available on your instance. (The optional docker-publishing blocks add `docker/setup-qemu-action` / `docker/login-action` only if you uncomment them.)
3. **Container/package registry** — Docker image publishing is **off by default** (mirrors the binary-only baseline). To publish images, uncomment the docker tools in `mise.toml` and the QEMU + registry-login block in the release/snapshot workflows. On a Forgejo instance the registry shares the instance host (e.g. `git.sylvlab.fr`); set the login `registry:` accordingly (detected via the shared `detect_registry()` helper).
4. **Release token & SCM (goreleaser)** — This is the one place the shared GitHub release template is *not* drop-in correct for Forgejo. The shared `release.yml` exports only `GITHUB_TOKEN` and the GitHub templates assume goreleaser publishes to github.com. Publishing a release to your Forgejo/Gitea instance instead requires **both**:
- A **`gitea_urls:` block in `.goreleaser.yml`** pointing goreleaser at your instance API (e.g. `api: https://git.sylvlab.fr/api/v1`, `download: https://git.sylvlab.fr`). This switches goreleaser to its **gitea** release publisher. Generate/edit it with `/gen-goreleaser`.
- The release job to export **`GITEA_TOKEN`** — goreleaser's gitea publisher reads this variable, not `GITHUB_TOKEN`. This skill adds `GITEA_TOKEN` to the generated `.forgejo/workflows/release.yml` (Phase 3.5), defaulting it to the job token Forgejo auto-provides (exposed as `secrets.GITHUB_TOKEN`). For broader scope (cross-repo pushes, package registry), create a dedicated `GITEA_TOKEN` repository secret and reference it instead.
Without both, the release job either targets github.com or fails to authenticate against your instance. `snapshot.yml` is unaffected — it runs goreleaser in `--snapshot` mode and never publishes.
## Content Generation Rules
**CRITICAL**: When generating any content (workflow files, commit messages, or any other output):
- **NEVER** add Claude Code attribution or co-authorship
- **NEVER** include phrases like "Generated by Claude", "Created with Claude Code", or similar
- **NEVER** add "Co-Authored-By: Claude" in commit messages or documentation
- All generated content should appear as if written by a human developer
- Focus on technical accuracy and providing working templates
## Process (6 Phases)
### Phase 1: Prerequisites Validation
**Critical checks before proceeding:**
1. **Validate Git repository:**
```bash
git rev-parse --git-dir
```
- If fails: Exit with error "Not a git repository. Run 'git init' first."
2. **Validate Go project:**
```bash
test -f go.mod
```
- If fails: Exit with error "go.mod not found. This skill is for Go projects only."
3. **Check existing .forgejo directory:**
```bash
test -d .forgejo
```
- If exists: Store `existingForgejoDir = true`
- If not exists: Store `existingForgejoDir = false`
4. **Verify skill assets directory:**
- Use Read tool to verify `${CLAUDE_PLUGIN_ROOT}/assets/github-workflows/workflows/linter.yml` exists
(Forgejo reuses the GitHub-Actions-compatible workflow templates.)
- Use Read tool to verify `${CLAUDE_PLUGIN_ROOT}/assets/mise/mise.toml` exists
- If either fails: Exit with error "Skill assets directory not found at ${CLAUDE_PLUGIN_ROOT}/assets/. Plugin may be corrupted. Reinstall the go-specialist plugin."
5. **Check existing mise.toml:**
```bash
test -f mise.toml
```
- Store `existingMise = true|false`. The workflows depend on `mise.toml`; if it
is missing this skill creates one (Phase 3.5). An existing one is preserved.
### Phase 2: Argument Parsing
Parse skill arguments from `$argument` string:
**Supported flags:**
- `--force`: Skip confirmation for existing .forgejo directory
- `--minimal`: Generate only essential files (2 files: workflows/linter.yml, workflows/release.yml)
- `--dry-run`: Show preview without writing files
**Parsing logic:**
```
arguments = split($argument by space)
for each arg in arguments:
if arg == "--force": set forceMode = true
if arg == "--minimal": set minimalMode = true
if arg == "--dry-run": set dryRunMode = true
```
**File Selection:**
- **Standard mode** (default): All 4 workflow files
- workflows/linter.yml
- workflows/coverage.yml
- workflows/snapshot.yml
- workflows/release.yml
- **Minimal mode** (`--minimal`): 2 essential files
- workflows/linter.yml
- workflows/release.yml
> Note: Unlike `/gen-github-dir`, this skill does NOT generate `FUNDING.yml` or `dependabot.yml`. Forgejo does not use GitHub Sponsors funding files, and dependency updates on Forgejo are handled by the instance's own mechanisms (e.g. Renovate) rather than `dependabot.yml`.
### Phase 3: Template Reading
**Read all template files** from the shared GitHub-Actions-compatible skill assets directory:
**Files to read:**
1. **workflows/linter.yml**
- Path: `${CLAUDE_PLUGIN_ROOT}/assets/github-workflows/workflows/linter.yml`
- Target: `.forgejo/workflows/linter.yml`
2. **workflows/coverage.yml** [Skip if minimal mode]
- Path: `${CLAUDE_PLUGIN_ROOT}/assets/github-workflows/workflows/coverage.yml`
- Target: `.forgejo/workflows/coverage.yml`
3. **workflows/snapshot.yml** [Skip if minimal mode]
- Path: `${CLAUDE_PLUGIN_ROOT}/assets/github-workflows/workflows/snapshot.yml`
- Target: `.forgejo/workflows/snapshot.yml`
4. **workflows/release.yml**
- Path: `${CLAUDE_PLUGIN_ROOT}/assets/github-workflows/workflows/release.yml`
- Target: `.forgejo/workflows/release.yml`
5. **mise.toml** [Only if `existingMise == false`]
- Path: `${CLAUDE_PLUGIN_ROOT}/assets/mise/mise.toml`
- Target: `mise.toml` (repo root)
**Template handling:**
- Store content in memory for Phase 3.5 substitution
- The workflow templates are **static** apart from the `runs-on` runner label —
tool versioning lives in `mise.toml`.
- Preserve all `# CUSTOMIZE:` comments
**Error handling:**
- If any Read fails: Exit with error "Failed to read template file: {filename}. Plugin may be corrupted."
### Phase 3.5: Auto-Detection & Substitution
**Detection Function Library:** Use the shared detection functions from `${CLAUDE_PLUGIN_ROOT}/assets/detection-functions.md`. Read that file to get the bash detection functions (`detect_registry`, `detect_go_version`, `detect_golangci_lint_version`, `detect_goreleaser_version`, `strip_leading_v`, `substitute_version_placeholders`).
**Detection Workflow:**
1. **Detect Forgejo runner label (best-effort):**
- Prefer the Forgejo CLI when available to pick a real runner label instead of the `docker` default:
```bash
# Best-effort: pick the first label advertised by a registered runner
FORGEJO_RUNNER_LABEL=$(fgj actions runner list 2>/dev/null | awk 'NR>1 {print $NF; exit}')
```
- If `fgj` is not installed or returns nothing, fall back to the default label `docker`.
- `FORGEJO_RUNNER_LABEL=${FORGEJO_RUNNER_LABEL:-docker}`
2. **Substitute the runner label (`runs-on`):**
The shared GitHub templates use `runs-on: ubuntu-latest`. Rewrite this to the Forgejo runner label in every workflow template:
```bash
workflow_template=$(echo "$workflow_template" | sed "s|runs-on: ubuntu-latest|runs-on: ${FORGEJO_RUNNER_LABEL}|g")
```
- `runs-on` is the only substitution **every** workflow needs; `release.yml`
additionally gets the release-token injection below.
3. **Inject the Forgejo release token (`release.yml` only):**
The shared `release.yml` job env exports only `GITHUB_TOKEN`, which is correct
for github.com. For a Forgejo/Gitea release, goreleaser's **gitea** publisher
authenticates with `GITEA_TOKEN` (and needs a `gitea_urls:` block in
`.goreleaser.yml`). Add `GITEA_TOKEN` to the release job env in the generated
`.forgejo/workflows/release.yml`. This rewrites only the Forgejo copy held in
memory — the shared GitHub asset is never modified:
```bash
# Applies to the release.yml content only; snapshot.yml never publishes.
release_template=$(printf '%s' "$release_template" | sed \
's|^\( *\)GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}$|\1# Forgejo/Gitea release: goreleaser authenticates with GITEA_TOKEN (needs gitea_urls: in .goreleaser.yml).\n\1# Defaults to the job token Forgejo auto-provides (exposed as secrets.GITHUB_TOKEN);\n\1# for broader scope, create a GITEA_TOKEN repo secret and reference it here.\n\1GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\1GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}|')
```
- Apply to `release.yml` only — `snapshot.yml` runs goreleaser in `--snapshot`
mode and needs no release token, so leave it untouched.
- Pair this with a `gitea_urls:` block in `.goreleaser.yml` (see `/gen-goreleaser`),
otherwise goreleaser still defaults to publishing on github.com.
4. **Ensure `mise.toml` exists (create if missing):**
The workflows install tools from `mise.toml`. If the repo has no `mise.toml`,
create one from the asset with detected versions:
```bash
if [[ "$existingMise" != "true" ]]; then
GO_VERSION=$(detect_go_version)
GOLANGCI_LINT_VERSION=$(detect_golangci_lint_version) # gh release view (external GitHub repo)
GORELEASER_VERSION=$(detect_goreleaser_version)
GOLANGCI_LINT_VERSION_BARE=$(strip_leading_v "${GOLANGCI_LINT_VERSION:-v2.2.2}")
mise_template=$(substitute_version_placeholders "$mise_template" \
"GO_VERSION=${GO_VERSION:-1.25}" \
"GOLANGCI_LINT_VERSION_BARE=${GOLANGCI_LINT_VERSION_BARE:-2.2.2}" \
"GORELEASER_VERSION=${GORELEASER_VERSION:-v2.12.0}")
# Written in Phase 5.
fi
```
- If `existingMise == true`: do NOT modify the existing `mise.toml`; note it in the report.
- golangci-lint/goreleaser/go are external GitHub-hosted tools; keep the
GitHub-based version detection (Forgejo has no equivalent for third-party repos).
5. **Detect container registry (optional docker block):**
```bash
REGISTRY=$(detect_registry) # On a Forgejo instance like git.sylvlab.fr → git.sylvlab.fr
```
- Only relevant if you enable the optional docker-publishing block: on a Forgejo
instance the registry shares the instance host; set the login `registry:` value
accordingly.
6. **Handle missing values:**
- If `FORGEJO_RUNNER_LABEL` could not be detected: Use `docker` and note it in the report so the user can verify against `fgj actions runner list`.
- Non-blocking: User can still create files and edit `runs-on:` manually later.
### Phase 4: User Confirmation
**Build preview summary:**
```
Files to be created:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[If standard mode:]
✅ .forgejo/workflows/linter.yml
✅ .forgejo/workflows/coverage.yml
✅ .forgejo/workflows/snapshot.yml
✅ .forgejo/workflows/release.yml
Total: 4 files
[If minimal mode:]
✅ .forgejo/workflows/linter.yml
✅ .forgejo/workflows/release.yml
Total: 2 files
[If existingMise == false:]
✅ mise.toml (created — pins go/task/golangci-lint/goreleaser for dev + CI)
[If existingMise == true:]
ℹ️ mise.toml already exists — preserved (workflows will use it as-is)
✅ Auto-detected Configuration
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Forgejo Settings:
• Runner label: <FORGEJO_RUNNER_LABEL> (from `fgj actions runner list`, or default `docker`)
• Tool versions (mise.toml): Go <GO_VERSION>, golangci-lint <GOLANGCI_LINT_VERSION_BARE>, goreleaser <GORELEASER_VERSION>
• Container registry: <REGISTRY> (only used by the optional docker block)
[If existingForgejoDir == true:]
⚠️ WARNING: .forgejo directory already exists
[List existing files that will be overwritten:]
- .forgejo/workflows/linter.yml (will be overwritten)
- .forgejo/workflows/release.yml (will be overwritten)
```
**Dry run mode:**
If `dryRunMode == true`:
- Show preview summary above
- Show first 20 lines of each workflow file
- Display next steps guide
- Exit without creating files
**Confirmation logic:**
1. **If `--force` flag provided:** Skip confirmation, proceed to Phase 5
2. **If existing .forgejo without `--force`:**
```
Use AskUserQuestion:
Question: ".forgejo directory already exists. Overwrite existing workflow files?"
Options:
1. "Yes, overwrite files" [Recommended if upgrading workflows]
2. "Show full preview first"
3. "Cancel"
If option 2: Display full content preview, then re-ask confirmation
If option 3: Exit gracefully
```
3. **If new .forgejo directory:**
```
Use AskUserQuestion:
Question: "Create .forgejo directory with [N] files?"
Options:
1. "Yes, create files"
2. "Show preview first"
3. "Cancel"
```
### Phase 5: File Creation
**Directory creation:**
1. Create `.forgejo/workflows/` directory:
```bash
mkdir -p .forgejo/workflows
```
**File writing sequence:**
1. `mise.toml` [Only if `existingMise == false`] — repo root, version-substituted
2. `.forgejo/workflows/linter.yml`
3. `.forgejo/workflows/coverage.yml` [Skip if minimal mode]
4. `.forgejo/workflows/snapshot.yml` [Skip if minimal mode]
5. `.forgejo/workflows/release.yml`
**For each file:**
- Use Write tool with full file path
- Write content from Phase 3.5 templates (with substitutions applied)
- Track success/failure status
- Continue with remaining files if one fails (partial success acceptable)
**Error handling:**
- If directory creation fails: Exit with error
- If individual file write fails: Log error, continue with next file
- If all writes fail: Report failure with details
- If partial success: Report which files succeeded/failed
**Track results:**
```
successfulFiles = []
failedFiles = []
for each file:
try write:
if success: add to successfulFiles
if failure: add to failedFiles
```
### Phase 6: Validation & Success Report
**Post-creation validation:** for each file in `successfulFiles`, confirm it exists
(e.g. `test -f .forgejo/workflows/linter.yml`) and is non-zero; move any failure to
`failedFiles`.
**Report to the user** — cover these facts; no fixed layout required:
- **Files written:** each path with a total count — `.forgejo/workflows/linter.yml` and
`.forgejo/workflows/release.yml`, plus `.forgejo/workflows/coverage.yml` and
`.forgejo/workflows/snapshot.yml` in standard mode. Mark `mise.toml` as created vs.
preserved.
- **Detected values:** the runner label `<FORGEJO_RUNNER_LABEL>`, and — if `mise.toml` was
created — the pinned Go, golangci-lint and goreleaser versions.
- **Verify the runner label:** `fgj actions runner list` should show a registered runner
advertising `<FORGEJO_RUNNER_LABEL>`. If none does, register one with
`fgj actions runner register`, or edit `runs-on:` in `.forgejo/workflows/*.yml` to match
an existing label.
- **Confirm action mirroring:** the workflows reference only `actions/checkout` and
`jdx/mise-action`, which require the instance to mirror or proxy GitHub actions. If it
does not, replace those two `uses:` references with mirrored equivalents.
- **Tool versions:** pinned in `mise.toml`, not the workflow files — editing it changes both
local (`mise install`) and CI versions.
- **Release publisher (release.yml + .goreleaser.yml):** `release.yml` exports `GITEA_TOKEN`,
defaulting to the job token Forgejo auto-provides (`secrets.GITHUB_TOKEN`); for broader
scope, create a `GITEA_TOKEN` repo-level secret and reference it there. Add a
`gitea_urls:` block (the instance's api/download URLs) to `.goreleaser.yml` so goreleaser
publishes to Forgejo rather than github.com — generate or edit that file with
`/gen-goreleaser`.
- **Optional customizations:** to publish Docker images, uncomment the docker tools
(buildx, docker-cli) in `mise.toml` and the QEMU + registry-login block in `snapshot.yml`
and `release.yml`, setting the login registry to `<REGISTRY>`. The coverage threshold is
`limit-coverage: 70` in `.forgejo/workflows/coverage.yml`.
- **Next steps:** review the workflow files, confirm a runner is registered and online
(`fgj actions runner list`), then `git add .forgejo/ mise.toml` and
`git commit -m "ci: add mise-based Forgejo Actions workflows"`, `git push origin main`,
and check the repository's Actions tab — the workflows should run on the next push if a
runner is online.
**On failure:** report which files were written, which failed and why, and that `--force`
retries. Partial success is a warning, total failure an error — for a total failure also
name the likely causes (permissions, disk space, filesystem restrictions).
## Arguments
Arguments are parsed from the `argument` string parameter:
- **`--force`**: Skip confirmation prompt and overwrite existing files
- Use when: Upgrading existing workflows to latest templates
- Behavior: Files are overwritten directly (no backups)
- **`--minimal`**: Generate only 2 essential files
- Includes: workflows/linter.yml, workflows/release.yml
- Excludes: workflows/coverage.yml, workflows/snapshot.yml
- Use when: Quick CI/CD setup without advanced features
- **`--dry-run`**: Preview files without writing to disk
- Shows: File list, preview of content
- Writes: Nothing
- Use when: Reviewing what will be created before committing
**Parsing example:**
```
argument = "--force --minimal"
Split by space, check for each flag:
- forceMode = true
- minimalMode = true
- dryRunMode = false
```
## Error Handling
### Critical Errors (Exit Immediately)
**Not a Git repository:**
```
❌ Error: Not a git repository
This skill requires a Git repository. Initialize one:
git init
git add .
git commit -m "Initial commit"
```
**Not a Go project:**
```
❌ Error: go.mod not found
This skill is for Go projects only. Initialize a Go module:
go mod init git.sylvlab.fr/username/project
```
**Skill assets missing:**
```
❌ Error: Skill assets directory not found
The go-specialist plugin may be corrupted. Try:
1. Reinstalling the plugin
2. Updating Claude Code to latest version
3. Reporting issue at: https://github.com/sgaunet/claude-plugins/issues
```
### Warning Errors (Continue with Others)
**Existing .forgejo directory:**
- Without `--force`: Request user confirmation
- With `--force`: Overwrite silently
**Individual file write failure:**
- Log error message
- Continue with remaining files
- Report partial success at end
**Runner label not detectable (`fgj` unavailable):**
- Fall back to `docker`
- Note in final report so the user verifies against `fgj actions runner list`
### Recovery Actions
**If mkdir fails:**
```
❌ Error: Failed to create .forgejo directory
Check:
1. Current directory is writable
2. Sufficient disk space
3. No existing .forgejo file (not directory) blocking creation
Current permissions: [show with ls -ld .]
```
**If all writes fail:**
```
❌ Error: Failed to write any workflow files
This may indicate:
1. Permission issues in .forgejo directory
2. Disk full
3. File system mounted read-only
Check disk space: df -h .
Check permissions: ls -la .forgejo/
```
## File Mapping
Complete mapping from skill assets to target locations. Forgejo reuses the GitHub-Actions-compatible templates; only the target directory and the `runs-on` label differ.
| Source Path | Target (Relative to CWD) | Mode |
|-------------|--------------------------|------|
| `${CLAUDE_PLUGIN_ROOT}/assets/mise/mise.toml` | `mise.toml` | Create-if-missing |
| `${CLAUDE_PLUGIN_ROOT}/assets/github-workflows/workflows/linter.yml` | `.forgejo/workflows/linter.yml` | All |
| `${CLAUDE_PLUGIN_ROOT}/assets/github-workflows/workflows/coverage.yml` | `.forgejo/workflows/coverage.yml` | Standard |
| `${CLAUDE_PLUGIN_ROOT}/assets/github-workflows/workflows/snapshot.yml` | `.forgejo/workflows/snapshot.yml` | Standard |
| `${CLAUDE_PLUGIN_ROOT}/assets/github-workflows/workflows/release.yml` | `.forgejo/workflows/release.yml` | All |
**Mode Legend:**
- **All**: Created in both standard and minimal modes
- **Standard**: Only created in standard mode (skipped in minimal)
- **Create-if-missing**: Written only when the repo has no `mise.toml`; an existing one is preserved
## Difference vs /gen-github-dir
| Aspect | /gen-github-dir | /gen-forgejo-dir |
|--------|-----------------|------------------|
| Directory | `.github/workflows/` | `.forgejo/workflows/` |
| `runs-on` | `ubuntu-latest` | Forgejo runner label (`docker` default, or detected via `fgj`) |
| Actions source | GitHub Marketplace | Configurable registry (assumes GitHub action mirror/proxy) |
| Actions referenced | `actions/checkout`, `jdx/mise-action` | Same two (fewer to mirror) |
| Tool install | mise (`mise.toml`) | mise (`mise.toml`) |
| Runner | GitHub-hosted | Self-hosted Forgejo Actions runner (`fgj actions runner register`) |
| Registry (optional docker) | `ghcr.io` | Instance host (e.g. `git.sylvlab.fr`) |
| Release publishing | goreleaser → github.com via `GITHUB_TOKEN` | goreleaser → instance via `GITEA_TOKEN` + `gitea_urls:` in `.goreleaser.yml` |
| FUNDING.yml | Yes (GitHub Sponsors) | No (not applicable) |
| dependabot.yml | Yes | No (Forgejo handles deps differently, e.g. Renovate) |
| Workflow YAML | GitHub Actions syntax | Same syntax (Forgejo Actions is GitHub-compatible) |
## Integration with Other Skills
**Works with:**
- `/commit`: Commit generated .forgejo directory
- `/gen-goreleaser`: Generate .goreleaser.yml config (required for release/snapshot workflows)
- `/gen-linter`: Generate .golangci.yml config (required for linter workflow)
- `/gen-taskfiles`: Generate Taskfile.yml with `lint`, `snapshot`, `release` tasks
**Typical Workflow:**
```bash
# 1. Generate dev tooling first (Taskfile.yml + mise.toml)
/gen-taskfiles
# 2. Generate .forgejo directory (reuses mise.toml; creates it if you skipped step 1)
/gen-forgejo-dir
# 3. Generate supporting configs
/gen-linter # Creates .golangci.yml
/gen-goreleaser # Creates .goreleaser.yml
# 4. Ensure a runner is registered
fgj actions runner list # or: fgj actions runner register
# 5. Commit everything
git add .forgejo/ mise.toml Taskfile*.yml .golangci.yml .goreleaser.yml
git commit -m "ci: add mise-based Forgejo Actions workflows and supporting configs"
# 6. Push and verify
git push origin main
# Check: https://git.sylvlab.fr/username/repo/actions
```
## Prerequisites for Workflows
**Required for workflows to function:**
1. **A registered Forgejo Actions runner** advertising the `runs-on` label used in the workflows:
```bash
fgj actions runner list # Inspect runners and labels
fgj actions runner register # Register a new runner
```
2. **GitHub action mirroring enabled** on the instance so `uses: actions/checkout` and `uses: jdx/mise-action` resolve.
3. **mise.toml** (auto-created by this skill if missing) — pins the tool versions installed by `jdx/mise-action`. Managed canonically by `/gen-taskfiles`.
4. **Taskfile.yml** with required tasks (`lint`, `snapshot`, `release`):
```yaml
version: '3'
tasks:
lint:
cmds: [golangci-lint run ./...]
snapshot:
cmds: [goreleaser release --snapshot --clean]
release:
cmds: [goreleaser release --clean]
```
- Generate with `/gen-taskfiles` (also emits mise.toml).
5. **.golangci.yml** configuration — generate with `/gen-linter` (golangci-lint itself comes from mise.toml).
6. **.goreleaser.yml** configuration — generate with `/gen-goreleaser` (required for snapshot.yml and release.yml). To publish releases to your Forgejo/Gitea instance (not github.com) it must include a `gitea_urls:` block, and the release job must export `GITEA_TOKEN` (this skill adds it to `release.yml`, defaulting to the auto-provided job token).
## Template Customization Points
All template files include `# CUSTOMIZE:` comments marking required changes:
**mise.toml:**
- Tool versions (`go`, `golangci-lint`, `goreleaser`) → adjust as needed (used by dev + CI)
- Docker tools (`buildx`, `docker-cli`) → uncomment if publishing images
**workflows/*.yml:**
- `runs-on: <label>` → Match a label advertised by a registered Forgejo runner
- Tag patterns in release.yml → Adjust semver format if needed
- `GITEA_TOKEN` in release.yml → defaults to the auto-provided job token; swap to a `GITEA_TOKEN` repo secret for broader scope (requires `gitea_urls:` in `.goreleaser.yml`)
- Optional docker block in snapshot.yml / release.yml → uncomment for image publishing
**coverage.yml:**
- `limit-coverage: "70"` → Adjust coverage threshold
- `sed -i '/cmd/d'` → Remove if including cmd package in coverage
## Best Practices
**Before running this skill:**
1. Ensure git repository initialized
2. Have go.mod configured
3. Confirm a Forgejo Actions runner is registered (`fgj actions runner list`)
**After generation:**
1. Review all `# CUSTOMIZE:` comments in workflow files
2. Verify the `runs-on` label matches a registered runner
3. Create required supporting files (Taskfile.yml, .goreleaser.yml, .golangci.yml)
4. Commit with a meaningful message
5. Monitor first workflow runs in the Forgejo Actions tab
## Limitations
**This skill does NOT:**
- Generate Taskfile.yml (use `/gen-taskfiles` or create manually)
- Generate .goreleaser.yml (use `/gen-goreleaser`)
- Generate .golangci.yml (use `/gen-linter`)
- Register or configure Forgejo Actions runners (use `fgj actions runner ...`)
- Configure GitHub action mirroring on the instance (instance-admin task)
- Validate that workflows will work (requires proper runner + mirror setup)
**Scope boundaries:**
- Only handles the `.forgejo/workflows/` directory structure
- Reuses opinionated GitHub-Actions-compatible templates
- Assumes standard Go project structure and an instance with action mirroring
## Examples
```bash
# Standard generation (4 workflow files)
/gen-forgejo-dir
# Minimal setup (2 essential files)
/gen-forgejo-dir --minimal
# Preview before creating
/gen-forgejo-dir --dry-run
# Overwrite existing workflows
/gen-forgejo-dir --force
# Minimal with force (quick upgrade)
/gen-forgejo-dir --minimal --force
```
## Output Summary
**Standard mode (default):**
- 4 workflow files + mise.toml (if missing)
- Comprehensive, mise-based CI/CD pipeline (lint, coverage, snapshot, release)
**Minimal mode (`--minimal`):**
- 2 workflow files + mise.toml (if missing)
- Essential linting + releases
**Dry run mode (`--dry-run`):**
- 0 files created
- Preview shown