Skip to content

Commit 688bb77

Browse files
author
Matthew
committed
Merge branch 'feat/swift-kotlin-standards' into 'main'
feat(standards): add Swift and Kotlin language standards, docs, and stories See merge request orgdocs/development-standards!34
2 parents 3d91a84 + fa938da commit 688bb77

19 files changed

+1720
-88
lines changed

DEVELOPMENT.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,8 @@ type(scope): description
274274
| `ruby` | Ruby tooling, configs, or standards |
275275
| `go` | Go tooling, configs, or standards |
276276
| `javascript` | JavaScript/TypeScript tooling, configs, or standards |
277+
| `swift` | Swift tooling, configs, or standards |
278+
| `kotlin` | Kotlin tooling, configs, or standards |
277279
| `container` | Dev-toolchain container image |
278280
| `ci` | CI/CD pipeline configuration |
279281
| `makefile` | Makefile targets and patterns |

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ The `standards/` directory contains the canonical reference documents for all De
4949
| [go.md](standards/go.md) | Go tooling standards (golangci-lint, gofumpt, govulncheck, go test) |
5050
| [javascript.md](standards/javascript.md) | JavaScript/TypeScript tooling standards (eslint, prettier, npm audit, vitest, tsc) |
5151
| [rust.md](standards/rust.md) | Rust tooling standards (clippy, rustfmt, cargo-audit, cargo-deny, cargo test) |
52+
| [swift.md](standards/swift.md) | Swift tooling standards (SwiftLint, swift-format, swift test, xcodebuild) |
53+
| [kotlin.md](standards/kotlin.md) | Kotlin tooling standards (ktlint, detekt, Gradle, Android Lint) |
5254
| [universal.md](standards/universal.md) | Universal security tools (trivy, gitleaks) |
5355
| [coding-practices.md](standards/coding-practices.md) | General coding principles, naming, error handling, testing, and dependencies |
5456
| [git-workflow.md](standards/git-workflow.md) | Branch strategy, pull requests, code review, merge policy, and git security |
Lines changed: 173 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Story 12.1: Add New Language Ecosystem (Template)
22

3-
Status: backlog
3+
Status: ready-for-dev
4+
5+
<!-- Note: Validation is optional. Run validate-create-story for quality check before dev-story. -->
6+
<!-- TEMPLATE STORY: Clone this file and replace [LANGUAGE]/[language] with the target language before development. -->
47

58
## Story
69

@@ -10,50 +13,191 @@ so that I get the same DevRail experience as all other supported languages.
1013

1114
## Acceptance Criteria
1215

13-
1. The dev-toolchain container includes all [LANGUAGE] tools (linter, formatter, security scanner, test runner)
14-
2. The Makefile supports [LANGUAGE] with lint, format, test, security, and fix targets
15-
3. A canonical standards document exists at `standards/[language].md`
16-
4. The devrail.dev site includes a [LANGUAGE] standards page
17-
5. Both template repos include [LANGUAGE] pre-commit hooks (commented out)
18-
6. `.devrail.yml` schema supports the new language entry
19-
7. `make check` passes across all repos
20-
8. A release is cut with the new language
16+
1. **Given** the dev-toolchain container, **When** a project declares `[language]` in `.devrail.yml`, **Then** `make lint` runs the [LANGUAGE] linter and reports results
17+
2. **Given** the dev-toolchain container, **When** a project declares `[language]` in `.devrail.yml`, **Then** `make format` checks [LANGUAGE] formatting and `make fix` applies fixes
18+
3. **Given** the dev-toolchain container, **When** a project declares `[language]` in `.devrail.yml`, **Then** `make test` runs the [LANGUAGE] test runner (gated on presence of test files/config)
19+
4. **Given** the dev-toolchain container, **When** a project declares `[language]` in `.devrail.yml`, **Then** `make security` runs [LANGUAGE]-specific security scanning (gated on lock file/config presence)
20+
5. **Given** `standards/[language].md`, **Then** it follows the consistent structure: Tools, Configuration, Makefile Targets, Pre-Commit Hooks, Notes
21+
6. **Given** `devrail-yml-schema.md`, **Then** `[language]` appears in the Allowed Values list and the Language Support Matrix
22+
7. **Given** the template repos, **Then** `.pre-commit-config.yaml` includes [LANGUAGE] hooks (commented out by default)
23+
8. **Given** `devrail init --languages [language]`, **Then** the init script scaffolds [LANGUAGE] config files and uncommments the pre-commit hooks
24+
9. **Given** all changes merged, **Then** `make check` passes on all 5 DevRail repos (dev-toolchain, development-standards, github-repo-template, gitlab-repo-template, devrail.dev)
25+
10. **Given** all changes merged to dev-toolchain, **Then** a new semver release is tagged and the container image is published to GHCR
2126

2227
## Tasks / Subtasks
2328

24-
- [ ] Task 1: Create install script (`dev-toolchain/scripts/install-[language].sh`)
25-
- [ ] Task 2: Create test script (`dev-toolchain/tests/test-[language].sh`)
26-
- [ ] Task 3: Update Dockerfile with language dependencies and install
27-
- [ ] Task 4: Update Makefile with `HAS_[LANGUAGE]` detection and targets
28-
- [ ] Task 5: Write `standards/[language].md`
29-
- [ ] Task 6: Write `devrail.dev/content/docs/standards/[language].md`
30-
- [ ] Task 7: Update both template `.pre-commit-config.yaml` files
31-
- [ ] Task 8: Update both template `.devrail.yml` files
32-
- [ ] Task 9: Update `devrail-yml-schema.md` with new language
33-
- [ ] Task 10: Update `devrail.dev` docs index and language matrix
34-
- [ ] Task 11: Update `STABILITY.md` and `README.md` in dev-toolchain
35-
- [ ] Task 12: Run `make check` on all repos
36-
- [ ] Task 13: Cut release
29+
- [ ] Task 1: Create install script (AC: 1, 2, 3, 4)
30+
- [ ] 1.1 Create `dev-toolchain/scripts/install-[language].sh` following the mandatory pattern (header, set -euo pipefail, lib sourcing, --help, cleanup trap, idempotent install functions, require_cmd verification)
31+
- [ ] 1.2 Install the linter: [LINTER] (idempotent: `command -v [linter]` or language-specific check before install)
32+
- [ ] 1.3 Install the formatter: [FORMATTER] (if different from linter)
33+
- [ ] 1.4 Install the security scanner: [SCANNER] (if language-specific, beyond trivy)
34+
- [ ] 1.5 Install the test runner: [TEST_RUNNER] (if not built-in to the language SDK)
35+
- [ ] 1.6 Verify all tools with `require_cmd` at end of each install function
36+
37+
- [ ] Task 2: Create verification test script (AC: 1, 2, 3, 4)
38+
- [ ] 2.1 Create `dev-toolchain/tests/test-[language].sh` using `assert_cmd` and `assert_version` helpers
39+
- [ ] 2.2 Verify linter is installed and runs: `assert_cmd [linter]`
40+
- [ ] 2.3 Verify formatter is installed and runs: `assert_cmd [formatter]`
41+
- [ ] 2.4 Verify test runner is available: `assert_cmd [test-runner]`
42+
- [ ] 2.5 Verify security tool is available (if language-specific)
43+
44+
- [ ] Task 3: Update Dockerfile (AC: 1, 2, 3, 4)
45+
- [ ] 3.1 Add builder stage if language requires SDK COPY (pattern: Go, Rust, Node.js, Swift)
46+
- [ ] 3.2 Add `COPY scripts/install-[language].sh /tmp/scripts/` and `RUN bash /tmp/scripts/install-[language].sh` to runtime stage
47+
- [ ] 3.3 Add environment variables if needed (e.g., JAVA_HOME, SWIFT_PATH)
48+
- [ ] 3.4 Build container and verify: `docker build .`
49+
50+
- [ ] Task 4: Update Makefile targets (AC: 1, 2, 3, 4)
51+
- [ ] 4.1 Add `HAS_[LANGUAGE] := $(filter [language],$(LANGUAGES))` detection variable
52+
- [ ] 4.2 Add [LANGUAGE] block to `_lint` target with proper error handling and fail-fast support
53+
- [ ] 4.3 Add [LANGUAGE] block to `_format` target (check mode)
54+
- [ ] 4.4 Add [LANGUAGE] block to `_fix` target (write mode)
55+
- [ ] 4.5 Add [LANGUAGE] block to `_test` target (gated on test file/config presence)
56+
- [ ] 4.6 Add [LANGUAGE] block to `_security` target (gated on lock file/config presence)
57+
- [ ] 4.7 Add [LANGUAGE] scaffolding to `_init` target (create default config files)
58+
- [ ] 4.8 Sync Makefile to both template repos
59+
60+
- [ ] Task 5: Write standards document (AC: 5)
61+
- [ ] 5.1 Create `standards/[language].md` with sections: Tools, Configuration, Makefile Targets, Pre-Commit Hooks, Notes
62+
- [ ] 5.2 Include annotated configuration examples for each tool
63+
- [ ] 5.3 Document gating conditions (which files must exist for each tool to run)
64+
65+
- [ ] Task 6: Update schema and documentation (AC: 6)
66+
- [ ] 6.1 Add `[language]` to Allowed Values in `standards/devrail-yml-schema.md`
67+
- [ ] 6.2 Add [LANGUAGE] column to Language Support Matrix in `devrail-yml-schema.md`
68+
- [ ] 6.3 Add `[language]` row to `README.md` standards table
69+
- [ ] 6.4 Add `[language]` scope to `DEVELOPMENT.md` conventional commits scopes
70+
71+
- [ ] Task 7: Update devrail.dev documentation site (AC: 6)
72+
- [ ] 7.1 Create `devrail.dev/content/docs/standards/[language].md` with Hugo/Docsy front matter
73+
- [ ] 7.2 Update `devrail.dev/content/docs/standards/_index.md` (matrix, target mapping, per-language links)
74+
75+
- [ ] Task 8: Configure pre-commit hooks (AC: 7)
76+
- [ ] 8.1 Find appropriate community pre-commit hooks for [LANGUAGE] (linter + formatter)
77+
- [ ] 8.2 Add hooks to both template repos' `.pre-commit-config.yaml` (commented out by default)
78+
- [ ] 8.3 Pin hook versions explicitly
79+
80+
- [ ] Task 9: Update devrail init (AC: 8)
81+
- [ ] 9.1 Add [LANGUAGE] to the language validation list in `devrail-init.sh`
82+
- [ ] 9.2 Add [LANGUAGE] config file scaffolding
83+
- [ ] 9.3 Add [LANGUAGE] pre-commit hook uncommenting logic
84+
85+
- [ ] Task 10: Update conventional commit scopes (AC: 9)
86+
- [ ] 10.1 Add `[language]` to the pre-commit-conventional-commits hook's valid scopes
87+
- [ ] 10.2 Tag a new version of the hook
88+
- [ ] 10.3 Update hook version in all repos' `.pre-commit-config.yaml`
89+
90+
- [ ] Task 11: Validate across all repos (AC: 9)
91+
- [ ] 11.1 Run `make check` on dev-toolchain
92+
- [ ] 11.2 Run `make check` on development-standards
93+
- [ ] 11.3 Run `make check` on github-repo-template
94+
- [ ] 11.4 Run `make check` on gitlab-repo-template
95+
- [ ] 11.5 Run `make check` on devrail.dev
96+
97+
- [ ] Task 12: Cut release (AC: 10)
98+
- [ ] 12.1 Update `STABILITY.md` in dev-toolchain
99+
- [ ] 12.2 Run `make release VERSION=X.Y.0`
100+
- [ ] 12.3 Verify GHCR image published
101+
- [ ] 12.4 Verify floating `v1` tag updated
37102

38103
## Dev Notes
39104

40-
- This is a **template story** — clone and customize for each new language (Elixir, Java, C#, etc.)
41-
- Follow the complete checklist in `standards/contributing.md` and the "Adding a New Language" section in MEMORY.md
42-
- Pattern: COPY SDK from official image in builder stage → install-[language].sh verifies (Go, Rust) or installs (Ruby, JS)
43-
- Pre-commit hooks: find appropriate community hooks or use local hooks
44-
- The conventional-commits hook (v1.1.0) already accepts all current language scopes — new languages need a scope added
105+
**This is a TEMPLATE STORY.** To use it:
106+
1. Clone this file as `12-N-add-[language]-language-ecosystem.md`
107+
2. Replace all `[LANGUAGE]` with the language name (title case) and `[language]` with the identifier (lowercase)
108+
3. Replace `[LINTER]`, `[FORMATTER]`, `[SCANNER]`, `[TEST_RUNNER]` with actual tool names
109+
4. Adjust tasks based on the language's specific tooling needs
110+
111+
### Architecture Patterns to Follow
112+
113+
**Container Strategy (choose one based on language):**
114+
- **SDK COPY pattern** (Go, Rust, Node.js, Swift): Multi-stage build, COPY SDK from official slim image to runtime stage. install-[language].sh is verify-only.
115+
- **Package manager install pattern** (Ruby, JavaScript): Runtime install via gem/npm. install-[language].sh runs `gem install` or `npm install -g`.
116+
- **System package pattern** (Python, Bash): Install via apt or pip. install-[language].sh runs apt-get/pip install.
117+
118+
**Makefile Target Pattern:**
119+
```makefile
120+
# Detection variable
121+
HAS_[LANGUAGE] := $(filter [language],$(LANGUAGES))
122+
123+
# Inside each target (_lint, _format, _fix, _test, _security):
124+
if [ -n "$(HAS_[LANGUAGE])" ]; then \
125+
ran_languages="$${ran_languages}\"[language]\","; \
126+
[command] || { overall_exit=1; failed_languages="$${failed_languages}\"[language]\","; }; \
127+
if [ "$(DEVRAIL_FAIL_FAST)" = "1" ] && [ $$overall_exit -ne 0 ]; then \
128+
# ... fail-fast JSON output ... \
129+
exit $$overall_exit; \
130+
fi; \
131+
fi;
132+
```
133+
134+
**Gating Conditions (common patterns):**
135+
- Lint/Format: gate on `*.[ext]` files existing
136+
- Test: gate on test files AND config file (e.g., `Package.swift`, `build.gradle.kts`, `Cargo.toml`)
137+
- Security: gate on lock/dependency file (e.g., `Package.resolved`, `Cargo.lock`, `go.sum`, `package-lock.json`)
138+
139+
**Install Script Mandatory Structure:**
140+
```bash
141+
#!/usr/bin/env bash
142+
# scripts/install-[language].sh -- Install [LANGUAGE] tooling for DevRail
143+
set -euo pipefail
144+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
145+
DEVRAIL_LIB="${DEVRAIL_LIB:-${SCRIPT_DIR}/../lib}"
146+
source "${DEVRAIL_LIB}/log.sh"
147+
source "${DEVRAIL_LIB}/platform.sh"
148+
# --help flag, cleanup trap, idempotent install functions, require_cmd verification
149+
```
150+
151+
### Multi-Repo PR Strategy
152+
153+
Submit PRs in this order (dependency chain):
154+
1. **pre-commit-conventional-commits** -- add `[language]` scope, tag new version
155+
2. **dev-toolchain** -- install script + Dockerfile + Makefile + tests + release
156+
3. **development-standards** -- standards doc + schema update
157+
4. **github-repo-template** -- pre-commit hooks + .devrail.yml
158+
5. **gitlab-repo-template** -- pre-commit hooks + .devrail.yml
159+
6. **devrail.dev** -- standards page + blog post
160+
161+
### Previous Language Additions (Reference)
162+
163+
| Language | Container Pattern | Install Pattern | Key Gotchas |
164+
|---|---|---|---|
165+
| Ruby | System Ruby 3.1 | `gem install` | bookworm ships 3.1 not 3.4; reek version pinning |
166+
| Go | COPY from `golang` image | verify-only | SDK needed at runtime for govulncheck |
167+
| JavaScript | COPY from `node:22-bookworm-slim` | `npm install -g` | manual npm/npx symlinks needed |
168+
| Rust | COPY from `rust:1-slim-bookworm` | verify-only | no curl in base; clippy/rustfmt need rustup component add |
169+
| Swift | COPY from `swift:6.1-slim-bookworm` | verify-only (planned) | xcodebuild macOS-only; SPM-first |
170+
| Kotlin | COPY JDK from `eclipse-temurin:21-jdk` | binary downloads | Android Lint needs Android SDK (CI-only) |
45171

46172
### References
47173

48-
- [Source: standards/contributing.md] — full checklist for adding a language
49-
- [Source: MEMORY.md → Adding a New Language — Checklist] — file-level checklist
174+
- [Source: standards/contributing.md] -- authoritative 8-step checklist with code examples
175+
- [Source: MEMORY.md -> Adding a New Language -- Checklist] -- file-level checklist
176+
- [Source: dev-toolchain/scripts/install-rust.sh] -- verify-only install pattern
177+
- [Source: dev-toolchain/scripts/install-ruby.sh] -- gem install pattern
178+
- [Source: dev-toolchain/scripts/install-javascript.sh] -- npm install pattern
179+
- [Source: standards/rust.md] -- most recent language standards doc format
180+
- [Source: devrail.dev/content/docs/standards/go.md] -- Hugo page format
50181

51182
## Dev Agent Record
52183

53184
### Agent Model Used
54185

186+
Claude Opus 4.6
187+
55188
### Debug Log References
56189

190+
- Analyzed all 10 existing language ecosystems for pattern extraction
191+
- Cross-referenced standards/contributing.md 8-step checklist
192+
- Extracted architecture constraints from architecture.md
193+
- Compiled previous language addition gotchas from MEMORY.md
194+
57195
### Completion Notes List
58196

197+
- Story enhanced from skeleton template to comprehensive dev agent guide
198+
- Includes concrete code patterns for Makefile targets, install scripts, and gating conditions
199+
- Previous language addition reference table prevents known gotchas
200+
- Multi-repo PR strategy documents dependency chain
201+
- All 12 tasks decomposed into atomic subtasks with AC traceability
202+
59203
### File List

0 commit comments

Comments
 (0)