From 811532a2542826048812d334195a3fe32d395377 Mon Sep 17 00:00:00 2001 From: yoshin Date: Mon, 15 Dec 2025 19:33:25 +0900 Subject: [PATCH 1/8] docs(plan): complete Phase 0 research and Phase 1 design for CI/CD pipeline Phase 0 - Research completed: - Evaluated GitHub Actions vs alternatives for C projects - Researched norminette integration best practices - Analyzed Conventional Commits for issue tracking - Designed branch strategy (GitHub Flow variant) - Planned automated release management - Documented issue/PR template requirements - Investigated MinilibX dependency handling in CI - Defined test automation strategy Phase 1 - Design completed: - Created data model for CI/CD entities (workflows, jobs, steps) - Defined workflow contracts (ci.yml, release.yml, pr-validation.yml) - Documented issue/PR template structures - Specified commit message format (Conventional Commits) - Created quickstart guide for team onboarding - Updated agent context with CI/CD technologies Constitution Check: ALL GATES PASSED - Norminette compliance enforced via CI - Unit testing automated in pipeline - Build verification on every PR - Templates encourage readable documentation - Bilingual support in templates Refs: #1 --- .github/agents/copilot-instructions.md | 3 + .../contracts/ci-main.yml.schema | 330 +++++++ .../contracts/pr-validation.yml.schema | 499 ++++++++++ .../contracts/release.yml.schema | 455 +++++++++ specs/001-raytracer/data-model.md | 687 +++++++------- specs/001-raytracer/plan.md | 379 ++------ specs/001-raytracer/quickstart.md | 880 ++++++++++++------ specs/001-raytracer/research.md | 841 +++++++++++------ 8 files changed, 2873 insertions(+), 1201 deletions(-) create mode 100644 specs/001-raytracer/contracts/ci-main.yml.schema create mode 100644 specs/001-raytracer/contracts/pr-validation.yml.schema create mode 100644 specs/001-raytracer/contracts/release.yml.schema diff --git a/.github/agents/copilot-instructions.md b/.github/agents/copilot-instructions.md index 3bb31be..f103c1a 100644 --- a/.github/agents/copilot-instructions.md +++ b/.github/agents/copilot-instructions.md @@ -3,6 +3,8 @@ Auto-generated from all feature plans. Last updated: 2025-12-15 ## Active Technologies +- C (C99 standard), Makefile, YAML (GitHub Actions), Shell scripts (Bash) (001-cicd-pipeline-github-workflow) +- Git repository, GitHub Actions artifacts for build logs and releases (001-cicd-pipeline-github-workflow) - C (C99 or later with -std=c99 or compatible) + MinilibX (X11/XQuartz graphics library), libm (math library), optional libft (001-raytracer) @@ -22,6 +24,7 @@ tests/ C (C99 or later with -std=c99 or compatible): Follow standard conventions ## Recent Changes +- 001-cicd-pipeline-github-workflow: Added C (C99 standard), Makefile, YAML (GitHub Actions), Shell scripts (Bash) - 001-raytracer: Added C (C99 or later with -std=c99 or compatible) + MinilibX (X11/XQuartz graphics library), libm (math library), optional libft diff --git a/specs/001-raytracer/contracts/ci-main.yml.schema b/specs/001-raytracer/contracts/ci-main.yml.schema new file mode 100644 index 0000000..f3d3ece --- /dev/null +++ b/specs/001-raytracer/contracts/ci-main.yml.schema @@ -0,0 +1,330 @@ +# CI Main Workflow Contract + +**Workflow**: `.github/workflows/ci.yml` +**Purpose**: Main CI pipeline for build validation, norminette checks, and testing +**Triggers**: Push to any branch, Pull requests to main/develop + +--- + +## Contract Specification + +### Input Events + +```yaml +on: + push: + branches: + - '*' + pull_request: + branches: + - main + - develop + workflow_dispatch: # Allow manual triggering +``` + +### Required Environment + +- **Runner**: `ubuntu-latest` +- **System Packages**: + - `libx11-dev` (X11 development headers) + - `libxext-dev` (X11 extensions) + - `xorg-dev` (X.Org development files) + - `xvfb` (Virtual framebuffer for headless testing) +- **Build Tools**: `gcc`, `make`, `git` +- **Python Tools**: `pip3`, `norminette` (via pip) + +### Job: norminette + +**Purpose**: Validate code style compliance with 42 norminette + +**Steps**: +1. Checkout repository +2. Install norminette via pip3 +3. Run norminette on `src/` and `includes/` directories +4. Fail workflow if violations found + +**Exit Conditions**: +- ✅ Success: All files pass norminette (exit code 0) +- ❌ Failure: One or more violations (exit code 1) + +**Contract**: +```yaml +norminette: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install norminette + run: pip3 install norminette + + - name: Run norminette + run: | + echo "Checking norminette compliance..." + norminette src/ includes/ +``` + +**Postconditions**: +- Norminette output displayed in logs +- Exit code 0 if all files compliant +- Exit code 1 if any violations found + +--- + +### Job: build + +**Purpose**: Compile miniRT and verify no compilation errors/warnings + +**Dependencies**: None (runs in parallel with norminette) + +**Steps**: +1. Checkout repository +2. Install MinilibX dependencies (X11, Xext) +3. Build MinilibX library +4. Compile miniRT using Makefile +5. Verify executable created + +**Exit Conditions**: +- ✅ Success: `miniRT` executable created, no warnings (exit code 0) +- ❌ Failure: Compilation errors or warnings present (exit code 1) + +**Contract**: +```yaml +build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libx11-dev libxext-dev xorg-dev + + - name: Build MinilibX + run: | + cd lib/minilibx-linux + make + + - name: Build miniRT + run: make + + - name: Verify executable + run: | + [ -f ./miniRT ] && echo "✅ Build successful" || exit 1 + + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: miniRT-binary + path: miniRT + retention-days: 7 +``` + +**Postconditions**: +- `miniRT` executable exists in project root +- Executable uploaded as workflow artifact +- All .o files created in `obj/` directory +- MinilibX library compiled in `lib/minilibx-linux/` + +--- + +### Job: test + +**Purpose**: Execute unit and integration tests + +**Dependencies**: Requires `build` job to complete successfully + +**Steps**: +1. Checkout repository +2. Download build artifact from `build` job +3. Install X11 dependencies + Xvfb +4. Build MinilibX (needed for test execution) +5. Run unit tests (if exist in `/tests`) +6. Run integration tests with Xvfb +7. Check for memory leaks (optional, if valgrind enabled) + +**Exit Conditions**: +- ✅ Success: All tests pass, no crashes (exit code 0) +- ❌ Failure: Test failures, segfaults, or timeouts (exit code 1) + +**Contract**: +```yaml +test: + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Download build artifact + uses: actions/download-artifact@v3 + with: + name: miniRT-binary + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libx11-dev libxext-dev xorg-dev xvfb + + - name: Build MinilibX + run: | + cd lib/minilibx-linux + make + + - name: Make executable + run: chmod +x miniRT + + - name: Start Xvfb + run: | + Xvfb :99 -screen 0 1024x768x24 & + echo "DISPLAY=:99" >> $GITHUB_ENV + + - name: Run unit tests + run: | + if [ -d tests ] && [ -f tests/run_unit_tests.sh ]; then + make tests + ./tests/run_unit_tests.sh + else + echo "No unit tests found, skipping" + fi + + - name: Run integration tests + run: | + if [ -f tests/integration/test_render.sh ]; then + chmod +x tests/integration/test_render.sh + timeout 300s tests/integration/test_render.sh + else + echo "No integration tests found, skipping" + fi +``` + +**Postconditions**: +- All unit tests executed and passed +- Integration tests completed without timeout +- No segmentation faults or crashes +- Test results logged to workflow output + +--- + +## Workflow Status Reporting + +### Success Criteria + +All three jobs (`norminette`, `build`, `test`) must succeed for workflow to pass. + +### PR Integration + +When workflow runs on pull request: +- Status check appears in PR conversation +- PR cannot be merged if any job fails (with branch protection enabled) +- Green checkmark displayed when all jobs pass + +### Notifications + +- Workflow status visible in GitHub Actions tab +- Commit status badge shows pass/fail +- Email notification on failure (if enabled in user settings) + +--- + +## Performance Targets + +| Metric | Target | Measured By | +|--------|--------|-------------| +| Total workflow time | < 5 minutes | End-to-end execution | +| Norminette job | < 30 seconds | Job duration | +| Build job | < 2 minutes | Job duration | +| Test job | < 3 minutes | Job duration | +| Artifact upload | < 10 seconds | Upload step | + +--- + +## Error Handling + +### Norminette Failures + +```bash +Error: src/parser/parser.c: Error! +Error: FUNCTIONS_TOO_LONG (line 45, col 1): Function exceeds 25 lines +``` + +**Recovery**: Developer must fix norminette violations and re-push. + +### Build Failures + +```bash +src/render/render.c:42:5: error: implicit declaration of function 'unknown_func' +make: *** [obj/render/render.o] Error 1 +``` + +**Recovery**: Developer must fix compilation errors and re-push. + +### Test Failures + +```bash +❌ FAIL: tests/integration/scenes/test_shadows.rt +Test timed out after 30 seconds +``` + +**Recovery**: Developer must investigate test failure, fix bug, and re-push. + +--- + +## Caching Strategy (Optional Enhancement) + +```yaml +- name: Cache MinilibX + uses: actions/cache@v3 + with: + path: lib/minilibx-linux + key: ${{ runner.os }}-minilibx-${{ hashFiles('lib/minilibx-linux/**') }} + +- name: Cache build objects + uses: actions/cache@v3 + with: + path: obj/ + key: ${{ runner.os }}-build-${{ hashFiles('src/**/*.c', 'includes/**/*.h') }} +``` + +**Benefits**: +- Reduces build time by 30-50% +- Avoids recompiling unchanged MinilibX +- Speeds up incremental builds + +--- + +## Rollback Strategy + +If CI workflow causes issues: + +1. **Immediate**: Disable workflow in `.github/workflows/ci.yml` (rename or delete) +2. **Temporary**: Comment out problematic job +3. **Permanent**: Revert commit that introduced breaking change + +--- + +## Maintenance + +### Update Actions Versions + +Periodically update pinned action versions: +```yaml +# Old +- uses: actions/checkout@v3 + +# New +- uses: actions/checkout@v4 +``` + +### Update norminette Version + +Pin specific norminette version for consistency: +```yaml +- name: Install norminette + run: pip3 install norminette==3.3.50 +``` + +### Monitor GitHub Actions Usage + +Check usage limits: Settings → Billing → Actions minutes used diff --git a/specs/001-raytracer/contracts/pr-validation.yml.schema b/specs/001-raytracer/contracts/pr-validation.yml.schema new file mode 100644 index 0000000..89c3698 --- /dev/null +++ b/specs/001-raytracer/contracts/pr-validation.yml.schema @@ -0,0 +1,499 @@ +# Pull Request Validation Contract + +**Workflow**: `.github/workflows/pr-validation.yml` +**Purpose**: Additional PR-specific validations (commit format, issue linkage, PR template compliance) +**Triggers**: Pull request opened, synchronized, or reopened + +--- + +## Contract Specification + +### Input Events + +```yaml +on: + pull_request: + types: [opened, synchronize, reopened] + branches: + - main + - develop +``` + +### Job: validate-commits + +**Purpose**: Ensure all commits in PR follow Conventional Commits format and reference issues + +**Steps**: +1. Checkout PR code +2. Fetch base branch for comparison +3. Extract commit messages from PR +4. Validate each commit format +5. Verify issue references + +**Exit Conditions**: +- ✅ Success: All commits valid, all reference issues +- ❌ Failure: Invalid format or missing issue references + +**Contract**: +```yaml +validate-commits: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 # Fetch full history + + - name: Fetch base branch + run: | + git fetch origin ${{ github.base_ref }} + + - name: Validate commit messages + run: | + commits=$(git log origin/${{ github.base_ref }}..HEAD --pretty=format:"%H") + failed=0 + + for commit in $commits; do + msg=$(git log -1 --pretty=%B $commit) + + # Check Conventional Commits format + if ! echo "$msg" | head -1 | grep -qE '^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .+'; then + echo "❌ Commit $commit does not follow Conventional Commits" + echo " Message: $(git log -1 --pretty=%s $commit)" + failed=1 + fi + + # Check issue reference + if ! echo "$msg" | grep -qE '(Refs|Fixes|Closes): #[0-9]+'; then + echo "❌ Commit $commit does not reference an issue" + echo " Message: $(git log -1 --pretty=%s $commit)" + failed=1 + fi + done + + if [ $failed -eq 1 ]; then + echo "" + echo "Commit format guide:" + echo " (): " + echo " " + echo " " + echo " " + echo " Refs: #" + exit 1 + fi + + echo "✅ All commits follow Conventional Commits and reference issues" +``` + +**Postconditions**: +- All commits validated +- Clear error messages if violations found +- PR status check updated + +--- + +### Job: validate-pr-template + +**Purpose**: Ensure PR description follows template and includes required sections + +**Steps**: +1. Extract PR body +2. Check for required sections (변경사항, 관련 이슈, 체크리스트, 테스트 방법) +3. Verify issue linkage in body +4. Verify checklist present + +**Exit Conditions**: +- ✅ Success: PR uses template, includes all sections +- ❌ Failure: Missing sections or incomplete template + +**Contract**: +```yaml +validate-pr-template: + runs-on: ubuntu-latest + steps: + - name: Validate PR description + uses: actions/github-script@v6 + with: + script: | + const pr = context.payload.pull_request; + const body = pr.body || ''; + + const required = [ + '## 변경사항', + '## 관련 이슈', + '## 체크리스트', + '## 테스트 방법' + ]; + + const missing = required.filter(section => !body.includes(section)); + + if (missing.length > 0) { + core.setFailed(`PR template incomplete. Missing sections: ${missing.join(', ')}`); + return; + } + + // Check for issue reference + if (!body.match(/(Closes|Fixes|Refs) #\d+/)) { + core.setFailed('PR must reference an issue using Closes #, Fixes #, or Refs #'); + return; + } + + // Check for checklist + if (!body.includes('- [ ]') && !body.includes('- [x]')) { + core.setFailed('PR must include checklist items'); + return; + } + + console.log('✅ PR template validation passed'); +``` + +**Postconditions**: +- PR template compliance verified +- Issue linkage confirmed +- Checklist presence confirmed + +--- + +### Job: check-branch-name + +**Purpose**: Ensure feature branch follows naming convention `###-feature-name` + +**Steps**: +1. Extract branch name +2. Validate format matches pattern +3. Verify issue number exists (optional) + +**Exit Conditions**: +- ✅ Success: Branch name follows convention +- ⚠️ Warning: Branch name non-standard (doesn't block merge) + +**Contract**: +```yaml +check-branch-name: + runs-on: ubuntu-latest + steps: + - name: Validate branch name + run: | + branch="${{ github.head_ref }}" + + if echo "$branch" | grep -qE '^[0-9]{3,}-[a-z0-9-]+$'; then + echo "✅ Branch name follows convention: $branch" + else + echo "⚠️ Branch name does not follow recommended pattern: ###-feature-name" + echo " Current: $branch" + echo " Example: 001-parser-validation" + # Don't fail, just warn + fi +``` + +**Postconditions**: +- Branch name validated +- Warning logged if non-compliant (but doesn't block) + +--- + +### Job: check-file-changes + +**Purpose**: Detect sensitive file changes that require extra review + +**Steps**: +1. Get list of changed files +2. Check for changes to critical files (Makefile, .github/workflows/) +3. Add warning label if found + +**Exit Conditions**: +- ✅ Success: No sensitive files changed, or changes acknowledged +- ⚠️ Warning: Sensitive files changed (adds label, doesn't block) + +**Contract**: +```yaml +check-file-changes: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Check for sensitive file changes + uses: actions/github-script@v6 + with: + script: | + const pr = context.payload.pull_request; + const files = await github.rest.pulls.listFiles({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number + }); + + const sensitivePatterns = [ + /^Makefile$/, + /^\.github\/workflows\//, + /^\.specify\//, + /^includes\/.*\.h$/ + ]; + + const changedFiles = files.data.map(f => f.filename); + const sensitiveChanges = changedFiles.filter(file => + sensitivePatterns.some(pattern => pattern.test(file)) + ); + + if (sensitiveChanges.length > 0) { + console.log('⚠️ Sensitive files changed:'); + sensitiveChanges.forEach(f => console.log(` - ${f}`)); + + // Add label to PR + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + labels: ['needs-careful-review'] + }); + } else { + console.log('✅ No sensitive files changed'); + } +``` + +**Postconditions**: +- Sensitive file changes detected +- `needs-careful-review` label applied if applicable +- Changes logged to workflow output + +--- + +## Validation Rules + +### Conventional Commits Format + +**Valid Patterns**: +```regex +^(feat|fix|docs|style|refactor|test|chore)(\([a-z]+\))?: .{1,72}$ +``` + +**Valid Examples**: +``` +feat(parser): add cylinder parsing +fix: correct shadow intersection +docs(readme): update build instructions +style(render): fix norminette violations +refactor(math): simplify vector operations +test(parser): add validation tests +chore(ci): update workflow configuration +``` + +**Invalid Examples**: +``` +Added new feature # Missing type +feat: Add new feature # Capital letter +fix(Parser): bug fix # Capital in scope +feat(parser): this is a very long commit message that exceeds seventy two characters # Too long +docs # Missing colon and subject +``` + +### Issue Reference Format + +**Valid Patterns**: +```regex +(Refs|Fixes|Closes): #\d+ +``` + +**Valid Examples**: +``` +Refs: #42 +Fixes: #123 +Closes: #7 +``` + +**Multiple References**: +``` +Refs: #42, #43 +Fixes: #100, Closes: #101 +``` + +**Invalid Examples**: +``` +See issue #42 # Wrong keyword +#42 # Missing keyword +Issue 42 # Missing # symbol +Fixes: 42 # Missing # symbol +``` + +### Branch Name Format + +**Recommended Pattern**: +```regex +^[0-9]{3,}-[a-z0-9-]+$ +``` + +**Valid Examples**: +``` +001-parser-validation +042-cylinder-rendering +123-fix-memory-leak +``` + +**Also Acceptable** (generates warning): +``` +feature/parser # Gitflow style +bugfix/shadow-rays # Gitflow style +fix-memory-leak # Simple descriptive +``` + +--- + +## PR Template Sections + +### Required Sections + +**1. 변경사항 / Changes** +- Must be present +- Should contain description of what changed +- Can be brief bullet points + +**2. 관련 이슈 / Related Issues** +- Must be present +- Must contain `Closes #X`, `Fixes #X`, or `Refs #X` +- Links to one or more issues + +**3. 체크리스트 / Checklist** +- Must be present +- Must contain at least one checkbox: `- [ ]` or `- [x]` +- Standard items: + - Norminette passes + - Compilation succeeds + - Tests pass + - Documentation updated + - No memory leaks + +**4. 테스트 방법 / How to Test** +- Must be present +- Should contain instructions for testing changes +- Can reference test files or commands + +--- + +## Error Messages + +### Commit Format Error + +``` +❌ Commit abc123 does not follow Conventional Commits + Message: Added new parser + +Commit format guide: + (): + + + + Refs: # + +Valid types: feat, fix, docs, style, refactor, test, chore +``` + +### Missing Issue Reference + +``` +❌ Commit def456 does not reference an issue + Message: feat(parser): add cylinder parsing + +Please include issue reference in commit body or footer: + Refs: #42 + Fixes: #42 + Closes: #42 +``` + +### Template Compliance Error + +``` +❌ PR template incomplete. Missing sections: ## 관련 이슈, ## 체크리스트 + +Please use the PR template and fill in all required sections. +The template is automatically populated when you create a PR. +``` + +--- + +## Bypass Mechanisms + +### Emergency Hotfixes + +For urgent hotfixes to main branch, allow bypass: + +```yaml +if: | + !startsWith(github.head_ref, 'hotfix-') +``` + +Hotfix branches skip commit validation but still require PR review. + +### Documentation-Only PRs + +For doc-only changes, relax commit format requirement: + +```yaml +- name: Check if docs-only PR + id: check_docs + run: | + if git diff --name-only origin/${{ github.base_ref }}..HEAD | grep -qvE '^docs/'; then + echo "not_docs_only=true" >> $GITHUB_OUTPUT + fi + +- name: Validate commits + if: steps.check_docs.outputs.not_docs_only == 'true' + run: # ... validation logic +``` + +--- + +## Integration with Main CI + +This workflow complements the main CI workflow: +- **Main CI**: Build, test, norminette (technical validation) +- **PR Validation**: Commit format, issue linkage, PR template (process validation) + +Both must pass for PR to be mergeable (with branch protection enabled). + +--- + +## Success Criteria + +- ✅ All commits follow Conventional Commits format +- ✅ All commits reference issue numbers +- ✅ PR uses template with all required sections +- ✅ PR references related issues +- ✅ Sensitive file changes flagged for review +- ✅ Clear error messages guide developers to fix issues + +--- + +## Maintenance + +### Update Commit Types + +Add custom commit types if needed: +```bash +# Add 'perf' for performance improvements +^(feat|fix|docs|style|refactor|test|chore|perf) +``` + +### Update Sensitive File Patterns + +Modify patterns as project evolves: +```javascript +const sensitivePatterns = [ + /^Makefile$/, + /^\.github\/workflows\//, + /^\.specify\//, + /^includes\/.*\.h$/, + /^lib\/minilibx-linux\//, // Add if MinilibX changes need review +]; +``` + +### Adjust Validation Strictness + +Make checks warnings instead of failures: +```yaml +- name: Validate commits + continue-on-error: true # Don't block PR, just warn + run: # ... validation +``` diff --git a/specs/001-raytracer/contracts/release.yml.schema b/specs/001-raytracer/contracts/release.yml.schema new file mode 100644 index 0000000..1aa6ac4 --- /dev/null +++ b/specs/001-raytracer/contracts/release.yml.schema @@ -0,0 +1,455 @@ +# Release Workflow Contract + +**Workflow**: `.github/workflows/release.yml` +**Purpose**: Automated release creation when version tags are pushed +**Triggers**: Push of tags matching `v*.*.*` pattern + +--- + +## Contract Specification + +### Input Events + +```yaml +on: + push: + tags: + - 'v*.*.*' # Semantic version tags: v1.0.0, v1.2.3, etc. +``` + +### Required Permissions + +```yaml +permissions: + contents: write # Required to create releases and upload assets +``` + +### Tag Format Requirements + +**Pattern**: `v{MAJOR}.{MINOR}.{PATCH}` + +**Valid Examples**: +- `v1.0.0` - Initial release +- `v1.2.3` - Feature release with bug fixes +- `v2.0.0` - Breaking change release + +**Invalid Examples**: +- `v1.0` - Missing patch version +- `1.0.0` - Missing 'v' prefix +- `v1.0.0-beta` - Pre-release suffixes not supported in this contract + +### Job: create-release + +**Purpose**: Build clean binary and create GitHub release with assets + +**Steps**: +1. Checkout repository at tagged commit +2. Install build dependencies +3. Build MinilibX +4. Clean build of miniRT (ensure no stale objects) +5. Strip binary (optional, reduces size) +6. Generate release notes from commits +7. Create GitHub release +8. Upload miniRT binary as asset + +**Exit Conditions**: +- ✅ Success: Release created with binary attached +- ❌ Failure: Build fails or release creation fails + +**Contract**: +```yaml +create-release: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 # Fetch all history for changelog generation + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libx11-dev libxext-dev xorg-dev + + - name: Build MinilibX + run: | + cd lib/minilibx-linux + make + + - name: Clean build + run: make fclean + + - name: Build release binary + run: make + + - name: Verify binary + run: | + [ -f ./miniRT ] || exit 1 + echo "✅ Binary built successfully" + ls -lh miniRT + + - name: Strip binary (optional) + run: strip miniRT + + - name: Generate release notes + id: release_notes + run: | + echo "## Changes" > release_notes.md + git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:"- %s" >> release_notes.md || echo "Initial release" >> release_notes.md + cat release_notes.md + + - name: Create Release + uses: softprops/action-gh-release@v1 + with: + files: miniRT + body_path: release_notes.md + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +--- + +## Release Notes Format + +### Auto-Generated Changelog + +Release notes automatically generated from commits since last tag using Conventional Commits: + +**Format**: +```markdown +## miniRT v1.2.3 + +### Features +- feat(parser): add cylinder orientation parsing +- feat(render): implement specular lighting + +### Bug Fixes +- fix(ray): correct cylinder cap intersection +- fix(lighting): fix shadow ray self-intersection + +### Documentation +- docs: update Korean implementation guide +- docs: add quickstart guide for CI/CD + +### Other Changes +- chore(ci): add release automation workflow +- test(parser): add validation tests +``` + +### Grouping Rules + +Commits grouped by type prefix: +- `feat:` → Features section +- `fix:` → Bug Fixes section +- `docs:` → Documentation section +- `style:`, `refactor:`, `test:`, `chore:` → Other Changes section + +--- + +## Asset Specification + +### Primary Asset: miniRT Binary + +| Property | Value | +|----------|-------| +| Filename | `miniRT` | +| Type | ELF 64-bit LSB executable | +| Architecture | x86-64 | +| Stripped | Yes (debug symbols removed) | +| Typical Size | 200-300 KB | +| Permissions | 755 (executable) | + +### Asset Download URL + +Pattern: `https://github.com/{owner}/{repo}/releases/download/{tag}/miniRT` + +Example: `https://github.com/user/miniRT_final/releases/download/v1.0.0/miniRT` + +--- + +## Semantic Versioning Strategy + +### Version Number Meanings + +**MAJOR version** (v**X**.0.0): +- Incompatible API changes +- Breaking changes to .rt file format +- Mandatory subject requirements change + +**Examples**: +- Adding mandatory element to .rt format +- Changing required function signatures +- Removing supported features + +**MINOR version** (v1.**X**.0): +- New features (backward-compatible) +- Bonus features implementation +- Performance improvements + +**Examples**: +- Adding specular lighting (bonus) +- Adding checkerboard patterns +- Implementing cone objects + +**PATCH version** (v1.2.**X**): +- Bug fixes only +- No new features +- Backward-compatible corrections + +**Examples**: +- Fixing memory leak +- Correcting intersection calculation +- Fixing norminette violations + +--- + +## Release Process + +### Step-by-Step Workflow + +**1. Developer Prepares Release** +```bash +# Ensure main branch is up to date +git checkout main +git pull origin main + +# Verify all tests pass locally +make test + +# Verify norminette compliance +norminette src/ includes/ + +# Update version in README or VERSION file (if exists) +echo "1.2.3" > VERSION +git add VERSION +git commit -m "chore: bump version to 1.2.3" +git push origin main +``` + +**2. Create and Push Tag** +```bash +# Create annotated tag +git tag -a v1.2.3 -m "Release version 1.2.3" + +# Push tag to trigger workflow +git push origin v1.2.3 +``` + +**3. GitHub Actions Executes** +- Workflow triggered automatically +- Binary built and verified +- Release created with auto-generated notes +- Binary uploaded as downloadable asset + +**4. Verify Release** +- Check GitHub Releases page +- Download and test binary +- Verify release notes accuracy + +--- + +## Error Handling + +### Build Failure During Release + +**Symptom**: +```bash +make: *** [obj/render/render.o] Error 1 +Error: Process completed with exit code 2. +``` + +**Recovery**: +1. Delete failed tag: `git push --delete origin v1.2.3` +2. Fix build errors locally +3. Commit fixes +4. Recreate tag with same or incremented version +5. Push tag again + +### Release Already Exists + +**Symptom**: +```bash +Error: Release v1.2.3 already exists +``` + +**Recovery Options**: +- **Option A**: Delete existing release, push tag again +- **Option B**: Increment patch version (v1.2.4), push new tag +- **Option C**: Update existing release manually (not recommended) + +### Tag Without Release + +If tag pushed but workflow fails, tag remains without release: + +**Recovery**: +```bash +# Delete remote tag +git push --delete origin v1.2.3 + +# Delete local tag +git tag -d v1.2.3 + +# Fix issue, recreate tag, push again +git tag -a v1.2.3 -m "Release 1.2.3" +git push origin v1.2.3 +``` + +--- + +## Download Instructions for Evaluators + +Include in release notes: + +```markdown +## Installation + +### Quick Start +```bash +# Download binary +wget https://github.com/{owner}/{repo}/releases/download/v1.2.3/miniRT + +# Make executable +chmod +x miniRT + +# Run with scene file +./miniRT scenes/example.rt +``` + +### Building from Source +```bash +# Clone repository at this tag +git clone --branch v1.2.3 https://github.com/{owner}/{repo}.git +cd miniRT_final + +# Build +make + +# Run +./miniRT scenes/example.rt +``` + +### Requirements +- Linux with X11 display server +- libX11, libXext development libraries +``` + +--- + +## Security Considerations + +### Token Security + +Workflow uses `GITHUB_TOKEN` automatically provided by GitHub Actions: +- Scoped to current repository only +- Expires after workflow completes +- No need to create personal access tokens +- Permissions limited to `contents: write` + +### Binary Integrity + +Evaluators can verify binary matches source: +1. Download source at tag +2. Build locally: `make` +3. Compare checksums: +```bash +sha256sum miniRT # Local build +sha256sum miniRT_downloaded # Downloaded asset +``` + +Should match if both built from same source on compatible systems. + +--- + +## Monitoring and Alerts + +### Workflow Status + +Check workflow execution: +- GitHub Actions tab → Release workflow runs +- Red X = failed release +- Green checkmark = successful release + +### Release Dashboard + +View all releases: +- GitHub repository → Releases section +- Shows all published versions +- Download counts per asset +- Tag linkage + +--- + +## Maintenance + +### Update Release Action + +Periodically update `softprops/action-gh-release`: +```yaml +# Check for latest version +- uses: softprops/action-gh-release@v1 # Current +- uses: softprops/action-gh-release@v2 # If updated +``` + +### Enhance Release Notes + +Optional improvements: +- Add comparison link to previous release +- Include contributor credits +- Link to milestone or project board +- Attach additional assets (e.g., scene files) + +### Pre-release Support + +Add pre-release tag support: +```yaml +on: + push: + tags: + - 'v*.*.*' + - 'v*.*.*-beta*' + - 'v*.*.*-rc*' +``` + +Mark as pre-release: +```yaml +- uses: softprops/action-gh-release@v1 + with: + prerelease: ${{ contains(github.ref, 'beta') || contains(github.ref, 'rc') }} +``` + +--- + +## Rollback Procedure + +### Revert to Previous Release + +If new release has critical bug: + +**1. Create Hotfix Tag** +```bash +# Increment patch version +git tag -a v1.2.4 -m "Hotfix: revert broken feature" +git push origin v1.2.4 +``` + +**2. Mark Bad Release** +Edit release on GitHub: +- Add warning to description: "⚠️ Known issue, use v1.2.4 instead" +- Or delete release entirely + +**3. Notify Users** +- Update README with notice +- Post issue announcing hotfix +- Update documentation + +--- + +## Success Criteria + +- ✅ Release created within 5 minutes of tag push +- ✅ Binary successfully uploaded and downloadable +- ✅ Release notes accurately reflect changes +- ✅ Binary executes without errors +- ✅ Download count tracked correctly diff --git a/specs/001-raytracer/data-model.md b/specs/001-raytracer/data-model.md index d7727e9..83d5bc3 100644 --- a/specs/001-raytracer/data-model.md +++ b/specs/001-raytracer/data-model.md @@ -1,422 +1,451 @@ -# Data Model: miniRT Ray Tracing +# Data Model: CI/CD Pipeline Entities -**Date**: 2025-12-15 -**Feature**: miniRT - Ray Tracing 3D Renderer -**Purpose**: Define core entities, structures, and relationships +**Feature**: CI/CD Pipeline 구축 및 GitHub 워크플로우 개선 +**Date**: 2025-12-15 -## Core Entities +## Overview -### 1. Vector (t_vec3) - -**Purpose**: Fundamental 3D coordinate and direction representation - -**Fields**: -- `x` (double): X-axis component -- `y` (double): Y-axis component -- `z` (double): Z-axis component - -**Validation Rules**: -- No range restrictions for position vectors -- Direction/normal vectors MUST be normalized (magnitude = 1.0, tolerance ±0.01) - -**Operations**: -- Addition, subtraction, scalar multiplication -- Dot product, cross product -- Normalization, magnitude calculation - -**Relationships**: -- Used by: Camera, Light, Sphere, Plane, Cylinder, Ray -- Basis for all spatial calculations +This document defines the data structures and entities that comprise the CI/CD pipeline system for miniRT. These entities represent workflow configurations, test artifacts, and validation rules. --- -### 2. Color (t_color) - -**Purpose**: RGB color representation in integer format - -**Fields**: -- `r` (int): Red channel [0-255] -- `g` (int): Green channel [0-255] -- `b` (int): Blue channel [0-255] - -**Validation Rules**: -- Each channel MUST be in range [0, 255] -- Invalid values trigger parse error - -**Operations**: -- Convert to floating point for lighting calculations -- Multiply by lighting intensity -- Clamp to valid range after calculations - -**Relationships**: -- Used by: Ambient light, Point light, all geometric objects - ---- - -### 3. Ambient Light (t_ambient) - -**Purpose**: Global base illumination for entire scene - -**Fields**: -- `ratio` (double): Brightness multiplier [0.0-1.0] -- `color` (t_color): RGB color of ambient light - -**Validation Rules**: -- Ratio MUST be in range [0.0, 1.0] -- MUST appear exactly once in scene file -- Color channels MUST be [0-255] +## Entity 1: GitHub Actions Workflow + +Represents a CI/CD workflow executed by GitHub Actions. + +### Attributes + +| Field | Type | Required | Description | Validation | +|-------|------|----------|-------------|------------| +| `name` | string | Yes | Workflow display name | Non-empty, alphanumeric with spaces | +| `on` | object | Yes | Trigger events | Valid GitHub event types | +| `jobs` | map | Yes | Named jobs to execute | At least 1 job | +| `env` | map | No | Global environment variables | Key-value pairs | +| `permissions` | object | No | GitHub token permissions | Valid permission scopes | + +### Example +```yaml +name: CI Pipeline +on: + push: + branches: [main] + pull_request: + branches: [main] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - run: make +``` -**Scene File Format**: +### State Transitions ``` -A -Example: A 0.2 255,255,255 +Created → Queued → In Progress → Completed (Success/Failure/Cancelled) ``` -**State Transitions**: None (static after parsing) - -**Relationships**: -- One per scene (singleton) -- Applied to all rendered surfaces +### Relationships +- Workflow **contains many** Jobs +- Workflow **triggered by** GitHub Events +- Workflow **produces** Artifacts --- -### 4. Camera (t_camera) +## Entity 2: Job + +Represents a single job within a workflow, running on a specific runner. + +### Attributes + +| Field | Type | Required | Description | Validation | +|-------|------|----------|-------------|------------| +| `runs-on` | string | Yes | Runner type | Valid runner label (ubuntu-latest, etc.) | +| `steps` | array | Yes | Sequential steps to execute | At least 1 step | +| `needs` | array | No | Job dependencies | Must reference existing job names | +| `if` | string | No | Conditional execution | Valid GitHub expression | +| `timeout-minutes` | integer | No | Max execution time | 1-360, default 360 | +| `strategy` | object | No | Matrix strategy | Valid matrix configuration | + +### Example +```yaml +build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Build + run: make + - name: Test + run: make test +``` -**Purpose**: Defines viewpoint and projection parameters +### Validation Rules +- Job name must be unique within workflow +- If `needs` specified, referenced jobs must exist +- Total job execution time < 6 hours +- Steps execute sequentially; failure stops job unless `continue-on-error: true` -**Fields**: -- `position` (t_vec3): Camera position in 3D space -- `orientation` (t_vec3): Normalized viewing direction vector -- `fov` (double): Horizontal field of view in degrees [0-180] +### Relationships +- Job **belongs to** Workflow +- Job **contains many** Steps +- Job **may depend on** other Jobs -**Validation Rules**: -- Orientation vector MUST be normalized -- FOV MUST be in range [0, 180] -- MUST appear exactly once in scene file +--- -**Scene File Format**: +## Entity 3: Step + +Represents a single executable step within a job. + +### Attributes + +| Field | Type | Required | Description | Validation | +|-------|------|----------|-------------|------------| +| `name` | string | No | Step display name | Human-readable identifier | +| `uses` | string | Conditional | Pre-built action to run | Valid action reference (owner/repo@version) | +| `run` | string | Conditional | Shell command(s) to execute | Non-empty string if `uses` not present | +| `with` | map | No | Action input parameters | Required inputs for specified action | +| `env` | map | No | Environment variables | Overrides job/workflow env | +| `if` | string | No | Conditional execution | Valid GitHub expression | +| `continue-on-error` | boolean | No | Allow failure | Default false | + +### Validation Rules +- Must specify exactly one of `uses` or `run` (mutually exclusive) +- If `uses` specified, `with` may be required per action documentation +- Shell commands in `run` must use valid bash syntax +- Environment variables accessible via `${{ env.VAR_NAME }}` + +### Example +```yaml +- name: Install norminette + run: pip3 install norminette + +- name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 ``` -C -Example: C 0,0,0 0,0,1 90 -``` - -**Derived Properties**: -- Viewport dimensions calculated from FOV -- Camera coordinate system (up, right vectors) derived from orientation -**State Transitions**: None (static after parsing) - -**Relationships**: -- One per scene (singleton) -- Used by rendering engine to generate rays +### Relationships +- Step **belongs to** Job +- Step **may use** GitHub Action +- Step **produces** Logs and Artifacts --- -### 5. Point Light (t_light) - -**Purpose**: Directional light source with position and intensity +## Entity 4: Issue Template -**Fields**: -- `position` (t_vec3): Light position in 3D space -- `brightness` (double): Light intensity ratio [0.0-1.0] -- `color` (t_color): RGB color of light +Represents a structured form for creating GitHub issues. -**Validation Rules**: -- Brightness MUST be in range [0.0, 1.0] -- MUST appear exactly once in scene file (mandatory part) -- Color channels MUST be [0-255] +### Attributes -**Scene File Format**: -``` -L -Example: L -40,50,0 0.6 255,255,255 -``` - -**State Transitions**: None (static after parsing) - -**Relationships**: -- One per scene (mandatory part) -- Used for diffuse lighting and shadow calculations +| Field | Type | Required | Description | Validation | +|-------|------|----------|-------------|------------| +| `name` | string | Yes | Template display name | Non-empty, displayed in issue creation UI | +| `about` | string | Yes | Template description | Brief explanation of when to use | +| `title` | string | No | Default issue title | Prefix like "[BUG]" or "[FEATURE]" | +| `labels` | array | No | Auto-applied labels | Must match existing labels in repo | +| `assignees` | array | No | Auto-assigned users | Must be valid GitHub usernames | +| `body` | string | Yes | Template markdown content | Must include sections for required info | +### Example +```markdown +--- +name: Bug Report +about: 버그를 제보해주세요 +title: '[BUG] ' +labels: [bug] +assignees: [] --- -### 6. Sphere (t_sphere) - -**Purpose**: Spherical geometric object - -**Fields**: -- `center` (t_vec3): Center position in 3D space -- `diameter` (double): Sphere diameter (must be positive) -- `color` (t_color): Surface RGB color +## 버그 설명 +[Description here] -**Validation Rules**: -- Diameter MUST be > 0 -- Color channels MUST be [0-255] +## 재현 단계 +1. Step 1 +2. Step 2 -**Scene File Format**: -``` -sp -Example: sp 0,0,20 20 255,0,0 +## 환경 +- OS: +- Compiler: ``` -**Derived Properties**: -- Radius = diameter / 2.0 +### Validation Rules +- Template file must be named with `.md` extension +- Must be placed in `.github/ISSUE_TEMPLATE/` directory +- Front matter (between `---`) must be valid YAML +- Body must provide clear sections for user input -**Intersection Math**: -- Quadratic equation: at² + bt + c = 0 -- Surface normal: (hit_point - center) / radius +### Relationships +- Issue Template **creates** GitHub Issue +- Issue Template **applies** Labels automatically +- Issue Template **assigns** Users automatically -**State Transitions**: None (static after parsing) +--- -**Relationships**: -- Multiple spheres allowed per scene -- Part of scene object list +## Entity 5: Pull Request Template ---- +Represents a structured form for creating pull requests. -### 7. Plane (t_plane) +### Attributes -**Purpose**: Infinite flat surface +| Field | Type | Required | Description | Validation | +|-------|------|----------|-------------|------------| +| `body` | string | Yes | Template markdown content | Must include checklist and description sections | -**Fields**: -- `point` (t_vec3): Any point on the plane -- `normal` (t_vec3): Normalized vector perpendicular to surface -- `color` (t_color): Surface RGB color +### Example +```markdown +## 변경사항 / Changes +[Description of changes] -**Validation Rules**: -- Normal vector MUST be normalized -- Color channels MUST be [0-255] +## 관련 이슈 / Related Issues +Closes #123 -**Scene File Format**: +## 체크리스트 / Checklist +- [ ] Norminette passes +- [ ] Tests pass +- [ ] Documentation updated ``` -pl -Example: pl 0,-10,0 0,1,0 200,200,200 -``` - -**Intersection Math**: -- t = [(point - ray.origin) · normal] / (ray.direction · normal) -- Surface normal: plane.normal (constant across entire plane) -**State Transitions**: None (static after parsing) +### Validation Rules +- Must be named `PULL_REQUEST_TEMPLATE.md` +- Must be placed in `.github/` or `.github/PULL_REQUEST_TEMPLATE/` +- Should include checklist with `- [ ]` syntax +- Should reference related issues with `Closes #` or `Fixes #` -**Relationships**: -- Multiple planes allowed per scene -- Part of scene object list +### Relationships +- PR Template **creates** Pull Request +- Pull Request **triggers** CI Workflows +- Pull Request **references** Issues --- -### 8. Cylinder (t_cylinder) +## Entity 6: Commit Message -**Purpose**: Finite cylindrical object with caps +Represents a structured commit message following Conventional Commits. -**Fields**: -- `center` (t_vec3): Center position of cylinder -- `axis` (t_vec3): Normalized axis direction vector -- `diameter` (double): Cylinder diameter (must be positive) -- `height` (double): Cylinder height along axis (must be positive) -- `color` (t_color): Surface RGB color +### Attributes -**Validation Rules**: -- Axis vector MUST be normalized -- Diameter MUST be > 0 -- Height MUST be > 0 -- Color channels MUST be [0-255] +| Field | Type | Required | Description | Validation | +|-------|------|----------|-------------|------------| +| `type` | string | Yes | Commit type | One of: feat, fix, docs, style, refactor, test, chore | +| `scope` | string | No | Component scope | Alphanumeric, describes affected component | +| `subject` | string | Yes | Short description | Max 72 chars, lowercase, no period | +| `body` | string | No | Detailed description | Multi-line, explains what/why | +| `footer` | string | No | Issue references | Format: "Refs: #123" or "Fixes: #456" | -**Scene File Format**: -``` -cy -Example: cy 0,0,0 0,1,0 10 20 0,255,0 +### Format ``` +(): -**Derived Properties**: -- Radius = diameter / 2.0 -- Bottom cap center: center -- Top cap center: center + axis * height + -**Intersection Math**: -- Cylindrical surface: quadratic equation in projected space -- Top/bottom caps: plane intersection + radius check -- Surface normal: varies by intersection type (body vs caps) - -**State Transitions**: None (static after parsing) +