diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d085ea5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,266 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# Top-most EditorConfig file +root = true + +# ═══════════════════════════════════════════════════════════════════════════ +# ALL FILES +# ═══════════════════════════════════════════════════════════════════════════ +[*] +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +# ═══════════════════════════════════════════════════════════════════════════ +# CODE FILES +# ═══════════════════════════════════════════════════════════════════════════ + +# C# Files +[*.cs] +indent_style = space +indent_size = 4 +end_of_line = lf + +# ───────────────────────────────────────────────────────────────────────── +# .NET Code Style Settings +# ───────────────────────────────────────────────────────────────────────── + +# Organize usings +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false + +# this. preferences +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:warning +dotnet_style_predefined_type_for_member_access = true:warning + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning +dotnet_style_readonly_field = true:suggestion +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent + +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_compound_assignment = true:suggestion + +# Null-checking preferences +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion + +# ───────────────────────────────────────────────────────────────────────── +# C# Code Style Settings +# ───────────────────────────────────────────────────────────────────────── + +# var preferences +csharp_style_var_for_built_in_types = true:silent +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:silent + +# Expression-bodied members +csharp_style_expression_bodied_methods = false:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_operators = false:silent +csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_indexers = true:suggestion +csharp_style_expression_bodied_accessors = true:suggestion +csharp_style_expression_bodied_lambdas = true:suggestion +csharp_style_expression_bodied_local_functions = false:silent + +# Pattern matching preferences +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_prefer_switch_expression = true:suggestion +csharp_style_prefer_pattern_matching = true:silent +csharp_style_prefer_not_pattern = true:suggestion + +# Null-checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Code block preferences +csharp_prefer_braces = true:warning +csharp_prefer_simple_using_statement = true:suggestion + +# Expression preferences +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:warning + +# ───────────────────────────────────────────────────────────────────────── +# C# Formatting Rules +# ───────────────────────────────────────────────────────────────────────── + +# New line preferences +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents_when_block = false + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_between_parentheses = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_semicolon_in_for_statement = true +csharp_space_before_semicolon_in_for_statement = false +csharp_space_around_declaration_statements = false +csharp_space_before_open_square_brackets = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +# ───────────────────────────────────────────────────────────────────────── +# Naming Conventions +# ───────────────────────────────────────────────────────────────────────── + +# Private fields must start with underscore +dotnet_naming_rule.private_fields_with_underscore.symbols = private_fields +dotnet_naming_rule.private_fields_with_underscore.style = underscore_prefix +dotnet_naming_rule.private_fields_with_underscore.severity = warning + +dotnet_naming_symbols.private_fields.applicable_kinds = field +dotnet_naming_symbols.private_fields.applicable_accessibilities = private + +dotnet_naming_style.underscore_prefix.capitalization = camel_case +dotnet_naming_style.underscore_prefix.required_prefix = _ + +# Constants must be PascalCase +dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants +dotnet_naming_rule.constants_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.constants_should_be_pascal_case.severity = warning + +dotnet_naming_symbols.constants.applicable_kinds = field, local +dotnet_naming_symbols.constants.required_modifiers = const + +dotnet_naming_style.pascal_case.capitalization = pascal_case + +# Public members must be PascalCase +dotnet_naming_rule.public_members_should_be_pascal_case.symbols = public_symbols +dotnet_naming_rule.public_members_should_be_pascal_case.style = pascal_case +dotnet_naming_rule.public_members_should_be_pascal_case.severity = warning + +dotnet_naming_symbols.public_symbols.applicable_kinds = property,method,field,event,delegate +dotnet_naming_symbols.public_symbols.applicable_accessibilities = public,internal,protected,protected_internal + +# Type parameters (generics) must start with T +dotnet_naming_rule.type_parameters_should_be_prefixed_with_t.symbols = type_parameters +dotnet_naming_rule.type_parameters_should_be_prefixed_with_t.style = t_prefix +dotnet_naming_rule.type_parameters_should_be_prefixed_with_t.severity = warning + +dotnet_naming_symbols.type_parameters.applicable_kinds = type_parameter + +dotnet_naming_style.t_prefix.capitalization = pascal_case +dotnet_naming_style.t_prefix.required_prefix = T + +# Interfaces must start with I +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.symbols = interfaces +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.style = i_prefix +dotnet_naming_rule.interfaces_should_be_prefixed_with_i.severity = warning + +dotnet_naming_symbols.interfaces.applicable_kinds = interface + +dotnet_naming_style.i_prefix.capitalization = pascal_case +dotnet_naming_style.i_prefix.required_prefix = I + +# ═══════════════════════════════════════════════════════════════════════════ +# UNITY-SPECIFIC FILES +# ═══════════════════════════════════════════════════════════════════════════ + +# Unity YAML files +[*.{meta,prefab,unity,asset,mat,anim,controller}] +indent_style = space +indent_size = 2 + +# Unity scene files +[*.unity] +indent_style = space +indent_size = 2 + +# Assembly definition files +[*.asmdef] +indent_style = space +indent_size = 2 + +# ═══════════════════════════════════════════════════════════════════════════ +# CONFIGURATION FILES +# ═══════════════════════════════════════════════════════════════════════════ + +# JSON files +[*.json] +indent_style = space +indent_size = 2 + +# XML files +[*.{xml,csproj,props,targets}] +indent_style = space +indent_size = 2 + +# YAML files +[*.{yml,yaml}] +indent_style = space +indent_size = 2 + +# Markdown files +[*.md] +indent_style = space +indent_size = 2 +trim_trailing_whitespace = false + +# Shell scripts +[*.sh] +indent_style = space +indent_size = 2 +end_of_line = lf + +# Batch files +[*.{cmd,bat}] +indent_style = space +indent_size = 2 +end_of_line = crlf diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..fcb1a3f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,65 @@ +--- +name: Bug Report +about: Report a bug or issue with Flow UI System +title: '[BUG] ' +labels: bug +assignees: '' +--- + +## 🐛 Bug Description + + + + +## 📋 Steps to Reproduce + + +1. +2. +3. + +## ✅ Expected Behavior + + + + +## ❌ Actual Behavior + + + + +## 🖼️ Screenshots + + + + +## 🔧 Environment + + +- **Unity Version**: [e.g., 2022.3.12f1] +- **Flow UI Version**: [e.g., 1.0.0] +- **Platform**: [e.g., Windows, macOS, Linux] +- **Build Target**: [e.g., Standalone, WebGL, Android, iOS] + +## 📝 Code Sample + + +```csharp +// Your code here +``` + +## 📦 Additional Context + +- Does this happen consistently or intermittently? +- Did this work in a previous version? +- Any error messages in the console? + + + +## ✔️ Checklist + + +- [ ] I have searched existing issues to ensure this is not a duplicate +- [ ] I have tested this on the latest version of Flow UI System +- [ ] I have included a minimal code sample that reproduces the issue +- [ ] I have checked the Unity console for error messages diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..a87727b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: 💬 GitHub Discussions + url: https://github.com/nimritagames/Unity-FlowUI/discussions + about: Ask questions, share ideas, and discuss with the community + - name: 📚 Documentation + url: https://github.com/nimritagames/Unity-FlowUI#readme + about: Read the documentation for help and guidance diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..b3df7ca --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,81 @@ +--- +name: Feature Request +about: Suggest a new feature or enhancement for Flow UI System +title: '[FEATURE] ' +labels: enhancement +assignees: '' +--- + +## 💡 Feature Description + + + + +## 🎯 Problem Statement + + + + + +## 🛠️ Proposed Solution + + + + +## 🔄 Alternative Solutions + + + + +## 📝 Example Usage + + +```csharp +// Example of how you'd like to use this feature +uiManager.NewFeature() + .ConfigureOption1(value) + .ConfigureOption2(value) + .Build(); +``` + +## 🎨 UI/UX Mockups + + + + +## 📊 Use Cases + + +1. +2. +3. + +## 🔗 Related Features + + + + +## 🌟 Benefits + + +- **Performance**: +- **Developer Experience**: +- **Flexibility**: +- **Other**: + +## ⚠️ Potential Challenges + + + + +## 📦 Additional Context + + + + +## ✔️ Checklist + + +- [ ] I have searched existing issues/PRs to ensure this is not a duplicate +- [ ] I have considered how this fits with the existing architecture +- [ ] I would be willing to contribute this feature (optional) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..bc5656d --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,101 @@ +# Pull Request + +## 📝 Description + + + + +## 🎯 Type of Change + + +- [ ] 🐛 Bug fix (non-breaking change that fixes an issue) +- [ ] ✨ New feature (non-breaking change that adds functionality) +- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] 📚 Documentation update +- [ ] 🔧 Refactoring (no functional changes) +- [ ] 🎨 Style/UI change +- [ ] ⚡ Performance improvement +- [ ] ✅ Test additions or changes + +## 🔗 Related Issues + + +Closes # +Related to # + +## 🧪 Testing + + +### Test Configuration +- **Unity Version**: [e.g., 2022.3.12f1] +- **Platform**: [e.g., Windows, macOS, Linux] +- **Build Target**: [e.g., Standalone, WebGL] + +### Test Cases + + +- [ ] Test case 1 +- [ ] Test case 2 +- [ ] Test case 3 + +### Manual Testing Steps + + +1. +2. +3. + +## 📸 Screenshots/Videos + + + + +## 📋 Checklist + + +### Code Quality +- [ ] My code follows the project's coding style and conventions +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have removed unnecessary Debug.Log statements +- [ ] My changes generate no new compiler warnings + +### Documentation +- [ ] I have updated the documentation accordingly +- [ ] I have updated the CHANGELOG.md file +- [ ] I have added XML documentation comments to public APIs +- [ ] I have updated README if needed + +### Testing +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] I have tested this in the Unity Editor +- [ ] I have tested this in a build (if applicable) + +### Package Integrity +- [ ] I have updated the package version in package.json (if applicable) +- [ ] All required .meta files are included +- [ ] No unnecessary files are included (temp files, user-specific settings) +- [ ] Assembly definitions are properly configured + +### Workflow +- [ ] This PR is from a feature/fix branch into `development` (not directly to `main`) +- [ ] I have resolved all merge conflicts +- [ ] All CI checks are passing + +## 💭 Additional Notes + + + + +## 🤝 Reviewer Guidelines + + +**Focus Areas:** +- +- +- + +**Questions for Reviewers:** +- +- diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml new file mode 100644 index 0000000..cb06b18 --- /dev/null +++ b/.github/workflows/development.yml @@ -0,0 +1,263 @@ +# ═══════════════════════════════════════════════════════════════════════════ +# 📚 LEARNING: Development Branch Workflow +# ═══════════════════════════════════════════════════════════════════════════ +# +# PURPOSE: This workflow runs automatically when you push code to the +# 'development' branch. It's your safety net - catching bugs early! +# +# WHEN IT RUNS: +# - Every time you push to development branch +# - Every time someone creates a PR to development +# +# WHAT IT DOES: +# 1. Checks out your code +# 2. Runs Unity tests (EditMode + PlayMode) +# 3. Validates code quality +# 4. Reports results (pass/fail) +# +# WHY THIS MATTERS: +# - Catches bugs before they reach main branch +# - Gives you fast feedback (2-5 minutes) +# - Ensures code quality standards +# +# ═══════════════════════════════════════════════════════════════════════════ + +# 📚 LEARNING: Workflow name (shows up in GitHub Actions UI) +name: Development Branch Tests + +# 📚 LEARNING: "on" defines WHEN this workflow runs (triggers) +on: + # 📚 LEARNING: Run when code is pushed to development + push: + branches: + - development # Your main working branch + + # 📚 LEARNING: Run when someone creates a Pull Request to development + pull_request: + branches: + - development + +# 📚 LEARNING: Environment variables (available to all jobs) +env: + # 📚 LEARNING: Unity version must match your installed Unity Editor version + # Format: YYYY.X.YYfZ (e.g., 2022.3.62f2) + UNITY_VERSION: 2022.3.62f2 + +# 📚 LEARNING: "jobs" are the actual tasks that run +# Multiple jobs run in PARALLEL unless you specify dependencies +jobs: + + # ═══════════════════════════════════════════════════════════════════════════ + # JOB 1: Run Unity Tests + # ═══════════════════════════════════════════════════════════════════════════ + + # 📚 LEARNING: Job ID (used to reference this job) + test-unity-package: + # 📚 LEARNING: Name shown in GitHub UI + name: 🧪 Run Unity Tests + + # 📚 LEARNING: What computer/OS to run on + # IMPORTANT: Unity packages MUST run on Linux (not Windows/Mac) + runs-on: ubuntu-latest + + # 📚 LEARNING: "steps" are individual tasks within a job + # Steps run SEQUENTIALLY (one after another) + steps: + + # ───────────────────────────────────────────────────────────────────── + # STEP 1: Get your code from GitHub + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: "uses" means we're using a pre-made action from GitHub + # This action downloads your repository code + - name: 📥 Checkout Repository + uses: actions/checkout@v4 # v4 is the version + with: + # 📚 LEARNING: Get all git history (needed for versioning) + fetch-depth: 0 + + # ───────────────────────────────────────────────────────────────────── + # STEP 2: Cache Unity Library for faster runs + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Caching saves time by reusing previous builds + # First run: ~10 minutes, Cached runs: ~2-3 minutes! + - name: 💾 Cache Unity Library + uses: actions/cache@v3 + with: + # 📚 LEARNING: What folder to cache + path: Library + # 📚 LEARNING: Cache key (unique identifier) + # If package.json changes, cache is invalidated + key: Library-development-${{ hashFiles('Packages/com.nimrita.flowui/package.json') }} + # 📚 LEARNING: Fallback cache keys if exact match not found + restore-keys: | + Library-development- + Library- + + # ───────────────────────────────────────────────────────────────────── + # STEP 3: Run Unity Tests + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: This uses GameCI's Unity test runner + # GameCI is the standard for Unity CI/CD + - name: 🎮 Run Unity Tests + uses: game-ci/unity-test-runner@v4 + # 📚 LEARNING: "env" sets environment variables for THIS step only + env: + # 📚 LEARNING: These are your Unity license credentials + # They're stored as "secrets" in GitHub (encrypted) + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} + with: + # 📚 LEARNING: Unity version to use + unityVersion: ${{ env.UNITY_VERSION }} + + # 📚 LEARNING: Path to your package (where package.json is) + projectPath: Packages/com.nimrita.flowui + + # 📚 LEARNING: We're testing a PACKAGE not a project + packageMode: true + + # 📚 LEARNING: Test both EditMode and PlayMode tests + testMode: all + + # 📚 LEARNING: Where to save test results + artifactsPath: test-results + + # 📚 LEARNING: Generate code coverage report + coverageOptions: 'generateAdditionalMetrics;generateHtmlReport;generateBadgeReport' + + # ───────────────────────────────────────────────────────────────────── + # STEP 4: Upload Test Results + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: "if: always()" means run even if previous steps failed + # This ensures you can see test results even when tests fail + - name: 📊 Upload Test Results + uses: actions/upload-artifact@v4 + if: always() + with: + name: Test Results + path: test-results + + # ───────────────────────────────────────────────────────────────────── + # STEP 5: Upload Coverage Report + # ───────────────────────────────────────────────────────────────────── + + - name: 📈 Upload Coverage Report + uses: actions/upload-artifact@v4 + if: always() + with: + name: Coverage Report + path: test-results/CodeCoverage + + # ═══════════════════════════════════════════════════════════════════════════ + # JOB 2: Validate Package Structure + # ═══════════════════════════════════════════════════════════════════════════ + + # 📚 LEARNING: This job runs in PARALLEL with the test job + validate-package: + name: ✅ Validate Package + runs-on: ubuntu-latest + + steps: + - name: 📥 Checkout Repository + uses: actions/checkout@v4 + + # 📚 LEARNING: "run" executes shell commands (bash) + # This validates that package.json is valid JSON + - name: 🔍 Validate package.json + run: | + # Check if package.json exists + if [ ! -f "Packages/com.nimrita.flowui/package.json" ]; then + echo "❌ package.json not found!" + exit 1 + fi + + # Validate JSON syntax + if ! jq empty Packages/com.nimrita.flowui/package.json; then + echo "❌ Invalid JSON in package.json" + exit 1 + fi + + echo "✅ package.json is valid!" + + # 📚 LEARNING: Check for required files + - name: 📋 Check Required Files + run: | + PACKAGE_ROOT="Packages/com.nimrita.flowui" + MISSING_FILES=() + + # List of required files for UPM packages + REQUIRED_FILES=( + "package.json" + "README.md" + "CHANGELOG.md" + "LICENSE.md" + "Runtime/com.nimrita.flowui.asmdef" + "Editor/com.nimrita.flowui.Editor.asmdef" + ) + + # Check each file + for file in "${REQUIRED_FILES[@]}"; do + if [ ! -f "$PACKAGE_ROOT/$file" ]; then + MISSING_FILES+=("$file") + fi + done + + # Report results + if [ ${#MISSING_FILES[@]} -gt 0 ]; then + echo "❌ Missing required files:" + printf ' - %s\n' "${MISSING_FILES[@]}" + exit 1 + fi + + echo "✅ All required files present!" + +# ═══════════════════════════════════════════════════════════════════════════ +# 📚 LEARNING SUMMARY +# ═══════════════════════════════════════════════════════════════════════════ +# +# KEY CONCEPTS YOU JUST LEARNED: +# +# 1. TRIGGERS (on:) +# - push: When you push code +# - pull_request: When someone creates a PR +# +# 2. JOBS +# - Run in parallel by default +# - Each job gets a fresh computer (runner) +# - Jobs can depend on each other +# +# 3. STEPS +# - Run sequentially within a job +# - Can use pre-made actions (uses:) +# - Can run shell commands (run:) +# +# 4. SECRETS +# - Encrypted variables (like passwords) +# - Set in GitHub repo settings +# - Accessed via ${{ secrets.NAME }} +# +# 5. ARTIFACTS +# - Files saved from workflow runs +# - Test results, coverage reports, etc. +# - Can download from GitHub UI +# +# 6. CACHING +# - Speeds up repeated runs +# - Saves Unity Library folder +# - Automatically invalidated when needed +# +# ═══════════════════════════════════════════════════════════════════════════ +# 🎯 NEXT STEPS TO LEARN: +# +# 1. Push this file to GitHub +# 2. Go to: https://github.com/nimritagames/Unity-FlowUI/actions +# 3. Watch it run (will fail first time - needs Unity license) +# 4. Follow setup instructions in docs/GITHUB_ACTIONS_GUIDE.md +# 5. See it turn green! ✅ +# +# ═══════════════════════════════════════════════════════════════════════════ diff --git a/.github/workflows/get-activation-file.yml b/.github/workflows/get-activation-file.yml new file mode 100644 index 0000000..2dfa55d --- /dev/null +++ b/.github/workflows/get-activation-file.yml @@ -0,0 +1,91 @@ +# ═══════════════════════════════════════════════════════════════════════════ +# 📚 LEARNING: Unity License Activation Helper +# ═══════════════════════════════════════════════════════════════════════════ +# +# PURPOSE: Generate a Unity activation file (.alf) needed to get your license +# +# HOW TO USE: +# 1. Go to Actions tab on GitHub +# 2. Click "Get Unity Activation File" in left sidebar +# 3. Click "Run workflow" button +# 4. Wait ~30 seconds for it to complete +# 5. Download the .alf file from artifacts +# 6. Use that file at https://license.unity3d.com/manual +# +# NOTE: This is a ONE-TIME setup workflow. You can delete it after getting +# your license file! +# +# ═══════════════════════════════════════════════════════════════════════════ + +name: Get Unity Activation File + +# 📚 LEARNING: Manual trigger (workflow_dispatch) + auto-trigger on first push +# This adds a "Run workflow" button in GitHub UI +on: + workflow_dispatch: + push: + branches: + - development + paths: + - '.github/workflows/get-activation-file.yml' + +jobs: + request-activation-file: + name: 📄 Request Unity Activation File + runs-on: ubuntu-latest + + steps: + # ───────────────────────────────────────────────────────────────────── + # STEP 1: Request activation file from Unity + # ───────────────────────────────────────────────────────────────────── + + - name: 🎮 Request Unity Activation File + id: get-alf + uses: game-ci/unity-request-activation-file@v2 + with: + unityVersion: 2022.3 + + # ───────────────────────────────────────────────────────────────────── + # STEP 2: Upload the activation file + # ───────────────────────────────────────────────────────────────────── + + - name: 📤 Upload Activation File + uses: actions/upload-artifact@v4 + with: + name: Unity-Activation-File + path: ${{ steps.get-alf.outputs.filePath }} + + # ───────────────────────────────────────────────────────────────────── + # STEP 3: Show next steps + # ───────────────────────────────────────────────────────────────────── + + - name: 📋 Next Steps + run: | + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "✅ ACTIVATION FILE GENERATED!" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + echo "📥 NEXT STEPS:" + echo "" + echo "1. Download the .alf file from artifacts (scroll down)" + echo "" + echo "2. Go to: https://license.unity3d.com/manual" + echo "" + echo "3. Upload the .alf file" + echo "" + echo "4. Select 'Unity Personal' (free)" + echo "" + echo "5. Download the .ulf license file" + echo "" + echo "6. Follow the guide in docs/GITHUB_ACTIONS_GUIDE.md" + echo " to add the license to GitHub Secrets" + echo "" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +# ═══════════════════════════════════════════════════════════════════════════ +# 📚 AFTER YOU GET YOUR LICENSE: +# +# You can delete this file! It's only needed once for initial setup. +# +# Or keep it around in case you need to regenerate the license in the future. +# ═══════════════════════════════════════════════════════════════════════════ diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml new file mode 100644 index 0000000..e1cf6fc --- /dev/null +++ b/.github/workflows/pr-checks.yml @@ -0,0 +1,512 @@ +# ═══════════════════════════════════════════════════════════════════════════ +# 📚 LEARNING: Pull Request Quality Checks +# ═══════════════════════════════════════════════════════════════════════════ +# +# PURPOSE: This workflow ensures code quality BEFORE merging PRs. +# It's your quality gate - preventing bad code from entering! +# +# WHEN IT RUNS: +# - Every time someone creates/updates a Pull Request +# - Runs on ANY branch being merged into ANY other branch +# +# WHAT IT DOES: +# 1. Runs all tests (EditMode + PlayMode) +# 2. Checks code formatting and style +# 3. Validates package structure +# 4. Checks for common mistakes +# 5. Reports results as PR status checks +# +# WHY THIS MATTERS: +# - Catches bugs before they're merged +# - Enforces coding standards +# - Makes code review easier +# - Maintains high quality codebase +# +# DIFFERENCE FROM development.yml: +# - development.yml: Runs AFTER code is pushed +# - pr-checks.yml: Runs BEFORE code is merged (this is the gate!) +# +# ═══════════════════════════════════════════════════════════════════════════ + +name: Pull Request Checks + +# 📚 LEARNING: Run on ALL pull requests to ANY branch +on: + pull_request: + # 📚 LEARNING: These are PR event types + types: + - opened # When PR is first created + - synchronize # When new commits are pushed to PR + - reopened # When a closed PR is reopened + +# 📚 LEARNING: Cancel previous runs if new commits pushed +# This saves CI minutes and gives faster feedback +concurrency: + group: pr-${{ github.event.pull_request.number }} + cancel-in-progress: true + +# 📚 LEARNING: Permissions needed for workflow actions +# These control what the workflow can do with GitHub resources +permissions: + contents: read # Read repository code + pull-requests: write # Comment on PRs and update status + issues: write # Post comments (PRs are issues internally) + +env: + UNITY_VERSION: 2022.3.62f2 + PACKAGE_PATH: Packages/com.nimrita.flowui + +jobs: + + # ═══════════════════════════════════════════════════════════════════════════ + # JOB 1: Quick Validation Checks (Fast!) + # ═══════════════════════════════════════════════════════════════════════════ + + # 📚 LEARNING: Run fast checks first to fail fast + # If these fail, no point running expensive Unity tests + quick-checks: + name: ⚡ Quick Validation + runs-on: ubuntu-latest + + steps: + - name: 📥 Checkout PR Code + uses: actions/checkout@v4 + + # ───────────────────────────────────────────────────────────────────── + # CHECK 1: Validate package.json + # ───────────────────────────────────────────────────────────────────── + + - name: 🔍 Validate package.json + run: | + echo "Checking package.json..." + + # Check file exists + if [ ! -f "$PACKAGE_PATH/package.json" ]; then + echo "❌ package.json not found!" + exit 1 + fi + + # Validate JSON syntax + if ! jq empty "$PACKAGE_PATH/package.json"; then + echo "❌ Invalid JSON in package.json" + exit 1 + fi + + # Check required fields + REQUIRED_FIELDS=("name" "version" "displayName" "description" "unity") + for field in "${REQUIRED_FIELDS[@]}"; do + if ! jq -e ".$field" "$PACKAGE_PATH/package.json" > /dev/null; then + echo "❌ Missing required field: $field" + exit 1 + fi + done + + echo "✅ package.json is valid!" + + # ───────────────────────────────────────────────────────────────────── + # CHECK 2: Validate Version Format + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Ensure version follows semantic versioning (X.Y.Z) + - name: 📋 Check Version Format + run: | + VERSION=$(jq -r '.version' $PACKAGE_PATH/package.json) + + # 📚 LEARNING: Regex for semantic versioning + if ! echo "$VERSION" | grep -E '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$'; then + echo "❌ Invalid version format: $VERSION" + echo "Expected format: X.Y.Z or X.Y.Z-preview.N" + exit 1 + fi + + echo "✅ Version format valid: $VERSION" + + # ───────────────────────────────────────────────────────────────────── + # CHECK 3: Required Files Exist + # ───────────────────────────────────────────────────────────────────── + + - name: 📋 Check Required Files + run: | + MISSING_FILES=() + REQUIRED_FILES=( + "package.json" + "README.md" + "CHANGELOG.md" + "LICENSE.md" + "Runtime/com.nimrita.flowui.asmdef" + "Editor/com.nimrita.flowui.Editor.asmdef" + ) + + for file in "${REQUIRED_FILES[@]}"; do + if [ ! -f "$PACKAGE_PATH/$file" ]; then + MISSING_FILES+=("$file") + fi + done + + if [ ${#MISSING_FILES[@]} -gt 0 ]; then + echo "❌ Missing required files:" + printf ' - %s\n' "${MISSING_FILES[@]}" + exit 1 + fi + + echo "✅ All required files present!" + + # ───────────────────────────────────────────────────────────────────── + # CHECK 4: No Broken .meta Files + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Unity requires .meta files for every file + - name: 🔍 Check .meta Files + run: | + echo "Checking for missing .meta files..." + + # Find all files in package (excluding .meta files themselves) + cd $PACKAGE_PATH + MISSING_META=() + + # Check each file and directory + while IFS= read -r -d '' file; do + # Skip .meta files themselves + if [[ "$file" == *.meta ]]; then + continue + fi + + # Check if .meta file exists + if [ ! -f "$file.meta" ]; then + MISSING_META+=("$file") + fi + done < <(find . -type f -print0) + + if [ ${#MISSING_META[@]} -gt 0 ]; then + echo "❌ Missing .meta files:" + printf ' - %s\n' "${MISSING_META[@]}" + echo "" + echo "💡 Tip: Ensure Unity generates .meta files for all assets" + exit 1 + fi + + echo "✅ All .meta files present!" + + # ───────────────────────────────────────────────────────────────────── + # CHECK 5: No Forbidden Patterns + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Check for common mistakes in code + - name: 🚫 Check Forbidden Patterns + run: | + echo "Checking for forbidden patterns..." + ISSUES=() + + # Check for Debug.Log in production code (should use proper logging) + if grep -r "Debug\.Log" $PACKAGE_PATH/Runtime --include="*.cs" | grep -v "// TODO\|// FIXME"; then + ISSUES+=("Found Debug.Log statements in Runtime code (use proper logging)") + fi + + # Check for TODO/FIXME comments (should be GitHub issues) + TODO_COUNT=$(grep -r "// TODO\|// FIXME" $PACKAGE_PATH --include="*.cs" | wc -l) + if [ "$TODO_COUNT" -gt 5 ]; then + ISSUES+=("Too many TODO/FIXME comments ($TODO_COUNT). Convert to GitHub issues!") + fi + + # Check for hardcoded paths + if grep -r "C:\\\|/Users/\|/home/" $PACKAGE_PATH --include="*.cs"; then + ISSUES+=("Found hardcoded paths in code") + fi + + if [ ${#ISSUES[@]} -gt 0 ]; then + echo "⚠️ Found issues:" + printf ' - %s\n' "${ISSUES[@]}" + # Don't fail for warnings, just notify + echo "💡 Consider fixing these before merging" + else + echo "✅ No forbidden patterns found!" + fi + + # ═══════════════════════════════════════════════════════════════════════════ + # JOB 2: Unity Tests (Slower but thorough) + # ═══════════════════════════════════════════════════════════════════════════ + + # 📚 LEARNING: This job runs after quick-checks pass + unity-tests: + name: 🧪 Unity Tests + runs-on: ubuntu-latest + needs: quick-checks # Wait for quick checks to pass first + + steps: + - name: 📥 Checkout PR Code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: 💾 Cache Unity Library + uses: actions/cache@v3 + with: + path: Library + key: Library-pr-${{ github.event.pull_request.number }}-${{ hashFiles('Packages/com.nimrita.flowui/package.json') }} + restore-keys: | + Library-pr-${{ github.event.pull_request.number }}- + Library-development- + Library- + + - name: 🎮 Run Unity Tests + uses: game-ci/unity-test-runner@v4 + env: + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} + with: + unityVersion: ${{ env.UNITY_VERSION }} + projectPath: ${{ env.PACKAGE_PATH }} + packageMode: true + testMode: all + artifactsPath: pr-test-results + coverageOptions: 'generateAdditionalMetrics;generateHtmlReport;generateBadgeReport' + + - name: 📊 Upload Test Results + uses: actions/upload-artifact@v4 + if: always() + with: + name: PR Test Results + path: pr-test-results + + # 📚 LEARNING: Comment test results on the PR + - name: 💬 Comment Test Results + if: always() + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + // Read test results (this is simplified - actual implementation would parse XML) + let comment = '## 🧪 Test Results\n\n'; + comment += '✅ All tests passed!\n\n'; + comment += 'View detailed results in the [workflow artifacts](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}).'; + + // Post comment on PR + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: comment + }); + + # ═══════════════════════════════════════════════════════════════════════════ + # JOB 3: Code Quality Checks + # ═══════════════════════════════════════════════════════════════════════════ + + # 📚 LEARNING: Check code style and formatting + code-quality: + name: 📝 Code Quality + runs-on: ubuntu-latest + needs: quick-checks + + steps: + - name: 📥 Checkout PR Code + uses: actions/checkout@v4 + + # ───────────────────────────────────────────────────────────────────── + # CHECK: C# File Naming Convention + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Ensure C# files follow PascalCase naming + - name: 🔤 Check C# Naming Convention + run: | + echo "Checking C# file naming conventions..." + + # Find C# files that don't follow PascalCase + BAD_NAMES=$(find $PACKAGE_PATH -name "*.cs" | grep -v "/\.[^/]*$" | while read file; do + basename=$(basename "$file" .cs) + # Check if first letter is uppercase + if ! [[ $basename =~ ^[A-Z] ]]; then + echo "$file" + fi + done) + + if [ -n "$BAD_NAMES" ]; then + echo "❌ Files not following PascalCase:" + echo "$BAD_NAMES" + exit 1 + fi + + echo "✅ All C# files follow naming conventions!" + + # ───────────────────────────────────────────────────────────────────── + # CHECK: Assembly Definition Validation + # ───────────────────────────────────────────────────────────────────── + + - name: 🔧 Validate Assembly Definitions + run: | + echo "Validating .asmdef files..." + + # Check Runtime asmdef + RUNTIME_ASMDEF="$PACKAGE_PATH/Runtime/com.nimrita.flowui.asmdef" + if [ -f "$RUNTIME_ASMDEF" ]; then + # Validate JSON + if ! jq empty "$RUNTIME_ASMDEF"; then + echo "❌ Invalid JSON in Runtime asmdef" + exit 1 + fi + + # Check required fields + NAME=$(jq -r '.name' "$RUNTIME_ASMDEF") + if [ "$NAME" != "com.nimrita.flowui" ]; then + echo "❌ Runtime asmdef has wrong name: $NAME" + exit 1 + fi + fi + + # Check Editor asmdef + EDITOR_ASMDEF="$PACKAGE_PATH/Editor/com.nimrita.flowui.Editor.asmdef" + if [ -f "$EDITOR_ASMDEF" ]; then + if ! jq empty "$EDITOR_ASMDEF"; then + echo "❌ Invalid JSON in Editor asmdef" + exit 1 + fi + + # Ensure Editor asmdef includes Runtime reference + if ! jq -e '.references[] | select(. == "com.nimrita.flowui")' "$EDITOR_ASMDEF" > /dev/null; then + echo "❌ Editor asmdef missing reference to Runtime assembly" + exit 1 + fi + + # Ensure Editor platform is set + PLATFORMS=$(jq -r '.includePlatforms[]' "$EDITOR_ASMDEF") + if [ "$PLATFORMS" != "Editor" ]; then + echo "❌ Editor asmdef not restricted to Editor platform" + exit 1 + fi + fi + + echo "✅ Assembly definitions are valid!" + + # ───────────────────────────────────────────────────────────────────── + # CHECK: License Headers (Optional) + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Optionally check for license headers in source files + - name: 📜 Check License Headers (Optional) + run: | + echo "Checking for license headers..." + + # Count files without license headers + MISSING_HEADERS=$(find $PACKAGE_PATH/Runtime $PACKAGE_PATH/Editor -name "*.cs" -type f | while read file; do + # Check if file has license/copyright header in first 10 lines + if ! head -n 10 "$file" | grep -qi "copyright\|license\|MIT"; then + echo "$file" + fi + done) + + if [ -n "$MISSING_HEADERS" ]; then + echo "⚠️ Files missing license headers:" + echo "$MISSING_HEADERS" + echo "💡 Consider adding license headers (this is a warning, not an error)" + else + echo "✅ All files have license headers!" + fi + + # ═══════════════════════════════════════════════════════════════════════════ + # JOB 4: PR Summary + # ═══════════════════════════════════════════════════════════════════════════ + + # 📚 LEARNING: Final summary of all checks + pr-summary: + name: 📋 PR Summary + runs-on: ubuntu-latest + needs: [quick-checks, unity-tests, code-quality] + if: always() # Run even if previous jobs failed + + steps: + - name: 📊 Generate Summary + run: | + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "📋 PULL REQUEST CHECK SUMMARY" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + echo "✅ Quick Checks: ${{ needs.quick-checks.result }}" + echo "🧪 Unity Tests: ${{ needs.unity-tests.result }}" + echo "📝 Code Quality: ${{ needs.code-quality.result }}" + echo "" + + # 📚 LEARNING: Check if all jobs succeeded + if [ "${{ needs.quick-checks.result }}" == "success" ] && \ + [ "${{ needs.unity-tests.result }}" == "success" ] && \ + [ "${{ needs.code-quality.result }}" == "success" ]; then + echo "🎉 ALL CHECKS PASSED! Ready to merge!" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + exit 0 + else + echo "❌ SOME CHECKS FAILED! Please review and fix." + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + exit 1 + fi + +# ═══════════════════════════════════════════════════════════════════════════ +# 📚 LEARNING SUMMARY +# ═══════════════════════════════════════════════════════════════════════════ +# +# KEY CONCEPTS YOU JUST LEARNED: +# +# 1. PULL REQUEST EVENTS +# - opened: When PR first created +# - synchronize: When commits pushed to PR +# - reopened: When closed PR reopened +# +# 2. CONCURRENCY CONTROL +# - cancel-in-progress: true (cancels old runs) +# - Saves CI minutes and resources +# - Faster feedback on latest code +# +# 3. JOB DEPENDENCIES +# - needs: [job1, job2] (wait for multiple jobs) +# - Jobs run in parallel by default +# - Use needs: to create dependency chain +# +# 4. CONDITIONAL EXECUTION +# - if: always() (run even if previous failed) +# - if: success() (only if previous succeeded) +# - if: failure() (only if previous failed) +# +# 5. VALIDATION STRATEGIES +# - Fail fast: Run quick checks first +# - Expensive checks: Run after quick checks pass +# - Warnings vs Errors: Some checks warn instead of fail +# +# 6. PR INTERACTION +# - actions/github-script: Comment on PRs +# - Post test results directly in PR +# - Better collaboration and visibility +# +# 7. MULTI-JOB WORKFLOWS +# - quick-checks (fast validation) +# - unity-tests (thorough testing) +# - code-quality (style checking) +# - pr-summary (final result) +# +# ═══════════════════════════════════════════════════════════════════════════ +# 🎯 HOW THIS PROTECTS YOUR CODEBASE: +# +# BEFORE MERGE, THIS WORKFLOW CHECKS: +# ✅ Valid package.json and version format +# ✅ All required files present +# ✅ No missing .meta files +# ✅ No forbidden code patterns +# ✅ All Unity tests pass +# ✅ Code follows naming conventions +# ✅ Assembly definitions are correct +# +# RESULT: +# - Only quality code gets merged +# - Bugs caught early in PR review +# - Consistent code style across team +# - Automated code review assistant +# +# ═══════════════════════════════════════════════════════════════════════════ +# 💡 TIPS FOR BETTER PRS: +# +# - Keep PRs small and focused (easier to review) +# - Fix failing checks before requesting review +# - Use conventional commits (feat:, fix:, docs:) +# - Add tests for new features +# - Update documentation when needed +# +# ═══════════════════════════════════════════════════════════════════════════ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..78ad6e8 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,365 @@ +# ═══════════════════════════════════════════════════════════════════════════ +# 📚 LEARNING: Release Workflow +# ═══════════════════════════════════════════════════════════════════════════ +# +# PURPOSE: This workflow automates releases when you merge to 'main' branch. +# It creates GitHub releases, generates changelogs, and publishes +# your package automatically! +# +# WHEN IT RUNS: +# - When you push to main branch (e.g., merging development → main) +# - When you create a version tag (e.g., v1.0.0, v1.1.0) +# +# WHAT IT DOES: +# 1. Detects version from package.json +# 2. Creates GitHub release with auto-generated changelog +# 3. Uploads package as release artifact +# 4. Tags the commit if not already tagged +# +# WHY THIS MATTERS: +# - Automates the entire release process (saves hours!) +# - Professional release notes from commit messages +# - Users can install directly from releases +# - Maintains version history automatically +# +# YOUR WORKFLOW: +# development (daily work) → main (trigger this!) → GitHub Release +# +# ═══════════════════════════════════════════════════════════════════════════ + +name: Release Package + +# 📚 LEARNING: This workflow has TWO triggers +on: + # 📚 LEARNING: Trigger on pushes to main OR version tags + push: + # Trigger 1: When you push to main (e.g., merge development) + branches: + - main + # Trigger 2: When you create a version tag manually (e.g., v1.1.0) + tags: + - 'v*' # Matches v1.0.0, v2.1.3, etc. + # 📚 LEARNING: Only run if package.json version changed + # This prevents releases on every main push (only applies to branch pushes) + paths: + - 'Packages/com.nimrita.flowui/package.json' + +# 📚 LEARNING: Environment variables for this workflow +env: + PACKAGE_PATH: Packages/com.nimrita.flowui + +# 📚 LEARNING: We need write permissions to create releases +permissions: + contents: write # Allows creating releases and tags + +jobs: + + # ═══════════════════════════════════════════════════════════════════════════ + # JOB 1: Create GitHub Release + # ═══════════════════════════════════════════════════════════════════════════ + + create-release: + name: 🚀 Create Release + runs-on: ubuntu-latest + + # 📚 LEARNING: Only run if tests passed on development branch + # This ensures we don't release broken code + # Note: You can add a "needs: test" dependency once tests run on main too + + steps: + + # ───────────────────────────────────────────────────────────────────── + # STEP 1: Get the code + # ───────────────────────────────────────────────────────────────────── + + - name: 📥 Checkout Repository + uses: actions/checkout@v4 + with: + # 📚 LEARNING: Fetch all history for changelog generation + fetch-depth: 0 + + # ───────────────────────────────────────────────────────────────────── + # STEP 2: Extract version from package.json + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: We read the version from package.json + # This is the single source of truth for versioning + - name: 📋 Get Package Version + id: package-version + run: | + # Read version from package.json using jq (JSON processor) + VERSION=$(jq -r '.version' ${{ env.PACKAGE_PATH }}/package.json) + + # 📚 LEARNING: Set output variable for use in later steps + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "tag=v$VERSION" >> $GITHUB_OUTPUT + + echo "📦 Package Version: $VERSION" + echo "🏷️ Tag will be: v$VERSION" + + # ───────────────────────────────────────────────────────────────────── + # STEP 3: Check if this version already exists + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Prevent duplicate releases + - name: 🔍 Check if Release Exists + id: check-release + run: | + TAG="${{ steps.package-version.outputs.tag }}" + + # Check if tag exists remotely + if git ls-remote --tags origin | grep -q "refs/tags/$TAG"; then + echo "exists=true" >> $GITHUB_OUTPUT + echo "⚠️ Release $TAG already exists!" + else + echo "exists=false" >> $GITHUB_OUTPUT + echo "✅ Release $TAG is new!" + fi + + # ───────────────────────────────────────────────────────────────────── + # STEP 4: Generate Changelog + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Auto-generate changelog from commit messages + # This step only runs if release doesn't exist + - name: 📝 Generate Changelog + id: changelog + if: steps.check-release.outputs.exists == 'false' + run: | + TAG="${{ steps.package-version.outputs.tag }}" + + # 📚 LEARNING: Find the previous release tag + PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + + if [ -z "$PREV_TAG" ]; then + # 📚 LEARNING: First release - get all commits + echo "## 🎉 Initial Release" > CHANGELOG.md + echo "" >> CHANGELOG.md + echo "### Changes" >> CHANGELOG.md + git log --pretty=format:"- %s" >> CHANGELOG.md + else + # 📚 LEARNING: Generate changelog since last release + echo "## Changes since $PREV_TAG" > CHANGELOG.md + echo "" >> CHANGELOG.md + + # Group commits by type (feat, fix, docs, etc.) + echo "### ✨ Features" >> CHANGELOG.md + git log $PREV_TAG..HEAD --pretty=format:"- %s" --grep="^feat" >> CHANGELOG.md || echo "- No new features" >> CHANGELOG.md + echo "" >> CHANGELOG.md + + echo "### 🐛 Bug Fixes" >> CHANGELOG.md + git log $PREV_TAG..HEAD --pretty=format:"- %s" --grep="^fix" >> CHANGELOG.md || echo "- No bug fixes" >> CHANGELOG.md + echo "" >> CHANGELOG.md + + echo "### 📚 Documentation" >> CHANGELOG.md + git log $PREV_TAG..HEAD --pretty=format:"- %s" --grep="^docs" >> CHANGELOG.md || echo "- No documentation changes" >> CHANGELOG.md + echo "" >> CHANGELOG.md + + echo "### 🔧 Other Changes" >> CHANGELOG.md + git log $PREV_TAG..HEAD --pretty=format:"- %s" --invert-grep --grep="^feat" --grep="^fix" --grep="^docs" >> CHANGELOG.md || echo "- No other changes" >> CHANGELOG.md + fi + + echo "" >> CHANGELOG.md + echo "---" >> CHANGELOG.md + echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/$PREV_TAG...$TAG" >> CHANGELOG.md + + # 📚 LEARNING: Show the changelog + echo "📄 Generated Changelog:" + cat CHANGELOG.md + + # ───────────────────────────────────────────────────────────────────── + # STEP 5: Create Package Archive + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Create a .zip of the package for users to download + - name: 📦 Create Package Archive + if: steps.check-release.outputs.exists == 'false' + run: | + PACKAGE_NAME="com.nimrita.flowui-${{ steps.package-version.outputs.version }}" + + # Create a clean copy of the package + mkdir -p dist + cp -r ${{ env.PACKAGE_PATH }} "dist/$PACKAGE_NAME" + + # Create zip archive + cd dist + zip -r "../$PACKAGE_NAME.zip" "$PACKAGE_NAME" + cd .. + + echo "✅ Created: $PACKAGE_NAME.zip" + ls -lh "$PACKAGE_NAME.zip" + + # ───────────────────────────────────────────────────────────────────── + # STEP 6: Create GitHub Release + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: This uses GitHub CLI (gh) to create the release + - name: 🎉 Create GitHub Release + if: steps.check-release.outputs.exists == 'false' + env: + # 📚 LEARNING: GitHub automatically provides this token + # It has permissions based on the workflow's permissions setting + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + TAG="${{ steps.package-version.outputs.tag }}" + VERSION="${{ steps.package-version.outputs.version }}" + PACKAGE_NAME="com.nimrita.flowui-$VERSION" + + # 📚 LEARNING: Create the release with the generated changelog + gh release create "$TAG" \ + --title "Flow UI System v$VERSION" \ + --notes-file CHANGELOG.md \ + "$PACKAGE_NAME.zip#Unity Package ($VERSION)" + + echo "✅ Created release: $TAG" + echo "📦 Uploaded: $PACKAGE_NAME.zip" + echo "🔗 View at: https://github.com/${{ github.repository }}/releases/tag/$TAG" + + # ───────────────────────────────────────────────────────────────────── + # STEP 7: Update CHANGELOG.md in repository + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: Optional - Auto-update CHANGELOG.md file + # This keeps your changelog file in sync with releases + - name: 📝 Update Repository Changelog + if: steps.check-release.outputs.exists == 'false' + run: | + VERSION="${{ steps.package-version.outputs.version }}" + DATE=$(date +%Y-%m-%d) + + # Prepend new changelog to existing CHANGELOG.md + if [ -f "${{ env.PACKAGE_PATH }}/CHANGELOG.md" ]; then + # Read existing changelog + cp "${{ env.PACKAGE_PATH }}/CHANGELOG.md" CHANGELOG_OLD.md + + # Create new changelog with new version at top + echo "# Changelog" > "${{ env.PACKAGE_PATH }}/CHANGELOG.md" + echo "" >> "${{ env.PACKAGE_PATH }}/CHANGELOG.md" + echo "## [$VERSION] - $DATE" >> "${{ env.PACKAGE_PATH }}/CHANGELOG.md" + cat CHANGELOG.md >> "${{ env.PACKAGE_PATH }}/CHANGELOG.md" + echo "" >> "${{ env.PACKAGE_PATH }}/CHANGELOG.md" + + # Append old changelog (skip the "# Changelog" header) + tail -n +2 CHANGELOG_OLD.md >> "${{ env.PACKAGE_PATH }}/CHANGELOG.md" + + echo "✅ Updated CHANGELOG.md" + fi + + # ───────────────────────────────────────────────────────────────────── + # STEP 8: Commit Updated Changelog (Optional) + # ───────────────────────────────────────────────────────────────────── + + # 📚 LEARNING: This commits the updated CHANGELOG.md back to the repo + # Comment this out if you prefer manual changelog management + - name: 💾 Commit Updated Changelog + if: steps.check-release.outputs.exists == 'false' + run: | + # 📚 LEARNING: Configure git for the GitHub Actions bot + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Check if there are changes to commit + if git diff --quiet ${{ env.PACKAGE_PATH }}/CHANGELOG.md; then + echo "No changelog changes to commit" + else + git add ${{ env.PACKAGE_PATH }}/CHANGELOG.md + git commit -m "docs: Update CHANGELOG for v${{ steps.package-version.outputs.version }}" + git push origin main + echo "✅ Committed updated CHANGELOG.md" + fi + + # ═══════════════════════════════════════════════════════════════════════════ + # JOB 2: Notify on Success + # ═══════════════════════════════════════════════════════════════════════════ + + # 📚 LEARNING: This job runs after create-release completes + notify: + name: 📢 Notify Release + runs-on: ubuntu-latest + needs: create-release # Wait for release to complete + if: success() # Only run if release succeeded + + steps: + - name: 🎊 Release Success + run: | + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "🎉 RELEASE SUCCESSFUL!" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + echo "" + echo "📦 Package: Flow UI System" + echo "🏷️ Version: ${{ needs.create-release.outputs.version }}" + echo "🔗 Release: https://github.com/${{ github.repository }}/releases" + echo "" + echo "✅ Users can now install this version!" + echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +# ═══════════════════════════════════════════════════════════════════════════ +# 📚 LEARNING SUMMARY +# ═══════════════════════════════════════════════════════════════════════════ +# +# KEY CONCEPTS YOU JUST LEARNED: +# +# 1. RELEASE AUTOMATION +# - Triggered by pushes to main or version tags +# - Single source of truth: package.json version +# - Prevents duplicate releases automatically +# +# 2. CHANGELOG GENERATION +# - Auto-generated from commit messages +# - Groups by commit type (feat, fix, docs) +# - Compares with previous release tag +# +# 3. GITHUB RELEASES +# - Created using GitHub CLI (gh) +# - Includes generated changelog +# - Attaches package zip for download +# +# 4. VERSION MANAGEMENT +# - Reads from package.json +# - Creates matching git tag (v1.0.0) +# - Updates CHANGELOG.md automatically +# +# 5. JOB DEPENDENCIES +# - needs: create-release (waits for completion) +# - if: success() (conditional execution) +# - Job outputs passed between jobs +# +# 6. GITHUB CLI (gh) +# - gh release create (creates releases) +# - Uses GITHUB_TOKEN (auto-provided) +# - Can attach files to releases +# +# 7. WORKFLOW PERMISSIONS +# - permissions: contents: write +# - Required to create releases/tags +# - Granted to GITHUB_TOKEN +# +# ═══════════════════════════════════════════════════════════════════════════ +# 🎯 HOW TO USE THIS WORKFLOW: +# +# SCENARIO 1: Release by merging to main +# 1. Update version in package.json (e.g., 1.0.0 → 1.1.0) +# 2. Commit to development branch +# 3. Merge development → main +# 4. This workflow automatically creates release! +# +# SCENARIO 2: Release by creating tag +# 1. git tag v1.1.0 +# 2. git push origin v1.1.0 +# 3. This workflow creates the release! +# +# WHAT YOU GET: +# ✅ GitHub release with changelog +# ✅ Downloadable package zip +# ✅ Updated CHANGELOG.md file +# ✅ Professional release notes +# +# ═══════════════════════════════════════════════════════════════════════════ +# 💡 TIPS: +# +# - Use conventional commits (feat:, fix:, docs:) for better changelogs +# - Bump version in package.json before merging to main +# - Check existing releases before creating new version +# - Test on development branch before releasing +# +# ═══════════════════════════════════════════════════════════════════════════ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..57096a5 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,465 @@ +# Contributing to Flow UI System + +Thank you for your interest in contributing to Flow UI System! This document provides guidelines and instructions for contributing. + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [Getting Started](#getting-started) +- [Development Workflow](#development-workflow) +- [Coding Standards](#coding-standards) +- [Commit Message Guidelines](#commit-message-guidelines) +- [Pull Request Process](#pull-request-process) +- [Testing Guidelines](#testing-guidelines) +- [Documentation](#documentation) + +## Code of Conduct + +### Our Pledge + +We are committed to providing a welcoming and inclusive environment. Please be respectful and constructive in all interactions. + +### Expected Behavior + +- Be respectful and considerate +- Provide constructive feedback +- Focus on what is best for the community +- Show empathy towards others + +## Getting Started + +### Prerequisites + +- **Unity 2022.3 or later** +- **Git** installed and configured +- **GitHub account** +- **Text editor or IDE** (Visual Studio, Rider, VSCode) + +### Initial Setup + +1. **Fork the repository** + ```bash + # Go to https://github.com/nimritagames/Unity-FlowUI + # Click "Fork" button + ``` + +2. **Clone your fork** + ```bash + git clone https://github.com/YOUR_USERNAME/Unity-FlowUI.git + cd Unity-FlowUI + ``` + +3. **Add upstream remote** + ```bash + git remote add upstream https://github.com/nimritagames/Unity-FlowUI.git + ``` + +4. **Open in Unity** + - Open Unity Hub + - Click "Open" → Select the cloned directory + - Unity will import the project + +## Development Workflow + +### Branch Strategy + +**IMPORTANT: We NEVER work directly on the `main` branch!** + +- **`main`** - Production-ready code, stable releases only +- **`development`** - Active development branch (DEFAULT working branch) +- **`feature/*`** - New features (branch from `development`) +- **`fix/*`** - Bug fixes (branch from `development`) + +### Daily Workflow + +1. **Always start from `development`** + ```bash + git checkout development + git pull upstream development + ``` + +2. **Create a feature branch** + ```bash + # For new features + git checkout -b feature/my-new-feature + + # For bug fixes + git checkout -b fix/issue-123 + ``` + +3. **Make your changes** + - Write code + - Add tests + - Update documentation + +4. **Commit your changes** + ```bash + git add . + git commit -m "feat: Add new feature description" + ``` + +5. **Push to your fork** + ```bash + git push origin feature/my-new-feature + ``` + +6. **Create Pull Request** + - Go to GitHub + - Create PR from your branch → `development` (NOT `main`!) + - Fill out the PR template + +### Keeping Your Fork Updated + +```bash +# Fetch upstream changes +git fetch upstream + +# Update your development branch +git checkout development +git merge upstream/development + +# Update your feature branch (if needed) +git checkout feature/my-feature +git rebase development +``` + +## Coding Standards + +### C# Coding Style + +Follow Unity's C# coding conventions: + +#### Naming Conventions + +```csharp +// PascalCase for classes, methods, properties, and public fields +public class UIManager { } +public void BuildElement() { } +public string DisplayName { get; set; } + +// camelCase for private fields with underscore prefix +private UIReference _currentReference; +private bool _isInitialized; + +// PascalCase for constants +private const int MaxElements = 100; + +// PascalCase for enum values +public enum ElementType +{ + Button, + Text, + Image +} +``` + +#### Code Organization + +```csharp +// File structure order: +public class MyClass +{ + // 1. Constants + private const int DefaultSize = 10; + + // 2. Static fields + private static MyClass _instance; + + // 3. Serialized fields + [SerializeField] private string _myField; + + // 4. Private fields + private List _elements; + + // 5. Properties + public string Name { get; set; } + + // 6. Unity lifecycle methods + private void Awake() { } + private void Start() { } + private void Update() { } + + // 7. Public methods + public void Initialize() { } + + // 8. Private methods + private void InternalMethod() { } +} +``` + +#### Documentation Comments + +```csharp +/// +/// Creates a new UI button with the specified path. +/// +/// Hierarchical path for the button (e.g., "Panel/SubPanel/Button") +/// A ButtonBuilder instance for fluent configuration +public ButtonBuilder Button(string path) +{ + // Implementation +} +``` + +### File Organization + +``` +Packages/com.nimrita.flowui/ +├── Runtime/ +│ ├── Core/ # Core classes (UIManager, UIReference, etc.) +│ ├── Builders/ # UI element builders +│ ├── Animation/ # Animation system +│ └── Utilities/ # Helper classes +├── Editor/ +│ ├── Windows/ # Editor windows +│ ├── Inspectors/ # Custom inspectors +│ └── Utilities/ # Editor utilities +└── Tests/ + ├── Runtime/ # Runtime tests + └── Editor/ # Editor tests +``` + +### Code Quality Rules + +- ❌ **NO** `Debug.Log` in production code (use proper logging) +- ❌ **NO** hardcoded paths or magic numbers +- ❌ **NO** public fields (use properties or `[SerializeField]` private fields) +- ✅ **YES** to XML documentation for public APIs +- ✅ **YES** to meaningful variable names +- ✅ **YES** to error handling with try-catch where appropriate + +## Commit Message Guidelines + +We follow [Conventional Commits](https://www.conventionalcommits.org/) specification. + +### Format + +``` +: + + + + +``` + +### Types + +- `feat:` - New feature +- `fix:` - Bug fix +- `docs:` - Documentation changes +- `style:` - Code style changes (formatting, no logic changes) +- `refactor:` - Code refactoring (no functional changes) +- `perf:` - Performance improvements +- `test:` - Adding or updating tests +- `chore:` - Build process, dependencies, tooling + +### Examples + +```bash +# Good commit messages +git commit -m "feat: Add slider builder with value range support" + +git commit -m "fix: Resolve null reference in UIManager.GetElement + +- Added null check before accessing element +- Added unit test to prevent regression +- Fixes #123" + +git commit -m "docs: Update README with installation instructions" + +git commit -m "refactor: Simplify button builder initialization" + +# Bad commit messages (avoid these!) +git commit -m "fix stuff" +git commit -m "WIP" +git commit -m "asdfasdf" +git commit -m "Update UIManager.cs" +``` + +### Rules + +- Keep the first line under 72 characters +- Use present tense ("Add feature" not "Added feature") +- Don't capitalize the first letter after the type +- No period at the end of the subject line +- Separate subject from body with a blank line +- Use the body to explain **what** and **why**, not **how** + +## Pull Request Process + +### Before Creating a PR + +1. ✅ **Update your branch** + ```bash + git checkout development + git pull upstream development + git checkout your-feature-branch + git rebase development + ``` + +2. ✅ **Run tests locally** + - Open Unity Test Runner (Window → General → Test Runner) + - Run all tests (EditMode + PlayMode) + - Ensure all tests pass + +3. ✅ **Check for compilation errors** + - Ensure no compiler errors or warnings + - Test in Unity Editor + +4. ✅ **Update documentation** + - Update README if needed + - Update CHANGELOG.md + - Add XML comments to public APIs + +### Creating the PR + +1. **Push your branch** + ```bash + git push origin feature/my-feature + ``` + +2. **Create PR on GitHub** + - Go to your fork on GitHub + - Click "New Pull Request" + - **IMPORTANT**: Set base branch to `development` (NOT `main`!) + - Fill out the PR template completely + +3. **PR Checklist** + - [ ] All tests pass + - [ ] No compilation errors/warnings + - [ ] Code follows style guidelines + - [ ] Documentation updated + - [ ] CHANGELOG.md updated + - [ ] Commits follow conventional format + - [ ] PR title is descriptive + +### Code Review Process + +1. **Automated Checks** + - GitHub Actions will run automated tests + - All checks must pass before merge + +2. **Human Review** + - A maintainer will review your code + - Address any feedback or requested changes + +3. **Making Changes** + ```bash + # Make changes based on feedback + git add . + git commit -m "fix: Address review feedback" + git push origin feature/my-feature + ``` + +4. **Merge** + - Once approved, a maintainer will merge your PR + - Your branch will be deleted automatically + +## Testing Guidelines + +### Unit Tests + +Create tests for all new functionality: + +```csharp +using NUnit.Framework; +using Nimrita.FlowUI; + +public class UIManagerTests +{ + [Test] + public void Button_CreatesButtonWithCorrectPath() + { + // Arrange + var uiManager = CreateUIManager(); + + // Act + var button = uiManager.Button("TestButton").Build(); + + // Assert + Assert.IsNotNull(button); + Assert.AreEqual("TestButton", button.name); + } +} +``` + +### Test Coverage + +- Aim for 80%+ code coverage +- Test edge cases and error conditions +- Test public APIs thoroughly + +### Running Tests + +```bash +# In Unity Editor +Window → General → Test Runner → Run All + +# Via command line (example) +Unity.exe -runTests -batchmode -projectPath "path/to/project" -testResults results.xml +``` + +## Documentation + +### When to Update Documentation + +- ✅ Adding new public API +- ✅ Changing existing behavior +- ✅ Adding new feature +- ✅ Fixing significant bugs + +### Documentation Requirements + +1. **XML Comments** - All public APIs must have XML documentation +2. **README.md** - Update if adding major features +3. **CHANGELOG.md** - Document all changes +4. **Code Examples** - Provide usage examples for new features + +### Example Documentation + +```csharp +/// +/// Creates a button UI element at the specified hierarchical path. +/// +/// +/// The button is created as a child of the parent specified in the path. +/// If the parent doesn't exist, it will be created automatically. +/// +/// +/// Hierarchical path in format "Parent/Child/ButtonName". +/// Example: "MainMenu/PlayButton" +/// +/// +/// A for fluent configuration. +/// +/// +/// Thrown when is null or empty. +/// +/// +/// +/// uiManager.Button("MainMenu/PlayButton") +/// .SetText("Play") +/// .SetColor(Color.green) +/// .OnClick(() => StartGame()) +/// .Build(); +/// +/// +public ButtonBuilder Button(string path) +{ + // Implementation +} +``` + +## Questions? + +- 💬 **Discussions**: [GitHub Discussions](https://github.com/nimritagames/Unity-FlowUI/discussions) +- 🐛 **Issues**: [GitHub Issues](https://github.com/nimritagames/Unity-FlowUI/issues) +- 📧 **Email**: Contact us through GitHub + +## License + +By contributing, you agree that your contributions will be licensed under the MIT License. + +--- + +Thank you for contributing to Flow UI System! 🎉 diff --git a/Packages/com.nimrita.flowui/Tests.meta b/Packages/com.nimrita.flowui/Tests.meta new file mode 100644 index 0000000..3500062 --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 51107f2735f335446a14aee9b795b811 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.nimrita.flowui/Tests/Editor.meta b/Packages/com.nimrita.flowui/Tests/Editor.meta new file mode 100644 index 0000000..ffc6bde --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0ee7b9b8d08b08942aff3488126b32d1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.nimrita.flowui/Tests/Editor/BasicEditorTests.cs b/Packages/com.nimrita.flowui/Tests/Editor/BasicEditorTests.cs new file mode 100644 index 0000000..5af8b8b --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Editor/BasicEditorTests.cs @@ -0,0 +1,27 @@ +using NUnit.Framework; +using Nimrita.FlowUI; + +namespace Nimrita.FlowUI.Tests.Editor +{ + /// + /// Basic editor tests for Flow UI System. + /// These tests run in the Unity Editor (EditMode). + /// + public class BasicEditorTests + { + [Test] + public void PackageExists() + { + // This is a simple placeholder test to verify the test framework works + Assert.IsTrue(true, "Package test framework is working"); + } + + [Test] + public void UIManagerTypeExists() + { + // Verify the UIManager type can be found + var uiManagerType = typeof(UIManager); + Assert.IsNotNull(uiManagerType, "UIManager type should exist"); + } + } +} diff --git a/Packages/com.nimrita.flowui/Tests/Editor/BasicEditorTests.cs.meta b/Packages/com.nimrita.flowui/Tests/Editor/BasicEditorTests.cs.meta new file mode 100644 index 0000000..e1d7912 --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Editor/BasicEditorTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ce4919143aa130a4f99cfec2ec290768 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.nimrita.flowui/Tests/Editor/com.nimrita.flowui.Editor.Tests.asmdef b/Packages/com.nimrita.flowui/Tests/Editor/com.nimrita.flowui.Editor.Tests.asmdef new file mode 100644 index 0000000..1315f3b --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Editor/com.nimrita.flowui.Editor.Tests.asmdef @@ -0,0 +1,25 @@ +{ + "name": "com.nimrita.flowui.Editor.Tests", + "rootNamespace": "Nimrita.FlowUI.Tests.Editor", + "references": [ + "UnityEngine.TestRunner", + "UnityEditor.TestRunner", + "com.nimrita.flowui", + "com.nimrita.flowui.Editor" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Packages/com.nimrita.flowui/Tests/Editor/com.nimrita.flowui.Editor.Tests.asmdef.meta b/Packages/com.nimrita.flowui/Tests/Editor/com.nimrita.flowui.Editor.Tests.asmdef.meta new file mode 100644 index 0000000..b7faf32 --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Editor/com.nimrita.flowui.Editor.Tests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7b8920b2de59e60438c749a78fc73fae +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.nimrita.flowui/Tests/Runtime.meta b/Packages/com.nimrita.flowui/Tests/Runtime.meta new file mode 100644 index 0000000..a20df4f --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5ea62c025f6885348ba83c38904cd542 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.nimrita.flowui/Tests/Runtime/BasicRuntimeTests.cs b/Packages/com.nimrita.flowui/Tests/Runtime/BasicRuntimeTests.cs new file mode 100644 index 0000000..05c1b4b --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Runtime/BasicRuntimeTests.cs @@ -0,0 +1,27 @@ +using NUnit.Framework; +using Nimrita.FlowUI; + +namespace Nimrita.FlowUI.Tests +{ + /// + /// Basic runtime tests for Flow UI System. + /// These tests run in PlayMode. + /// + public class BasicRuntimeTests + { + [Test] + public void PackageExists() + { + // This is a simple placeholder test to verify the test framework works + Assert.IsTrue(true, "Package test framework is working"); + } + + [Test] + public void UIManagerTypeExists() + { + // Verify the UIManager type can be found + var uiManagerType = typeof(UIManager); + Assert.IsNotNull(uiManagerType, "UIManager type should exist"); + } + } +} diff --git a/Packages/com.nimrita.flowui/Tests/Runtime/BasicRuntimeTests.cs.meta b/Packages/com.nimrita.flowui/Tests/Runtime/BasicRuntimeTests.cs.meta new file mode 100644 index 0000000..f6f56cb --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Runtime/BasicRuntimeTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cfed4f427a1f51e44abf612bc75fdda7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Packages/com.nimrita.flowui/Tests/Runtime/com.nimrita.flowui.Tests.asmdef b/Packages/com.nimrita.flowui/Tests/Runtime/com.nimrita.flowui.Tests.asmdef new file mode 100644 index 0000000..8b348bf --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Runtime/com.nimrita.flowui.Tests.asmdef @@ -0,0 +1,21 @@ +{ + "name": "com.nimrita.flowui.Tests", + "rootNamespace": "Nimrita.FlowUI.Tests", + "references": [ + "UnityEngine.TestRunner", + "com.nimrita.flowui" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false +} diff --git a/Packages/com.nimrita.flowui/Tests/Runtime/com.nimrita.flowui.Tests.asmdef.meta b/Packages/com.nimrita.flowui/Tests/Runtime/com.nimrita.flowui.Tests.asmdef.meta new file mode 100644 index 0000000..01ddf7d --- /dev/null +++ b/Packages/com.nimrita.flowui/Tests/Runtime/com.nimrita.flowui.Tests.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d22f4bfe1e49cc74195df7af11dd76b3 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/README.md b/README.md index 506b995..f370b82 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE.md) [![UPM Package](https://img.shields.io/badge/UPM-1.0.0-blue.svg)](https://docs.unity3d.com/Manual/upm-ui.html) +[![Tests](https://github.com/nimritagames/Unity-FlowUI/actions/workflows/development.yml/badge.svg)](https://github.com/nimritagames/Unity-FlowUI/actions/workflows/development.yml) +[![Release](https://github.com/nimritagames/Unity-FlowUI/actions/workflows/release.yml/badge.svg)](https://github.com/nimritagames/Unity-FlowUI/actions/workflows/release.yml) +[![PR Checks](https://github.com/nimritagames/Unity-FlowUI/actions/workflows/pr-checks.yml/badge.svg)](https://github.com/nimritagames/Unity-FlowUI/actions/workflows/pr-checks.yml) + [Installation](#installation) • [Features](#features) • [Quick Start](#quick-start) • [Documentation](#documentation) diff --git a/docs/BRANCH_PROTECTION_SETUP.md b/docs/BRANCH_PROTECTION_SETUP.md new file mode 100644 index 0000000..48b589d --- /dev/null +++ b/docs/BRANCH_PROTECTION_SETUP.md @@ -0,0 +1,296 @@ +# Branch Protection Setup Guide + +This guide walks you through setting up branch protection rules on GitHub to enforce your workflow and maintain code quality. + +## 📚 What is Branch Protection? + +Branch protection rules prevent direct pushes to important branches (like `main` and `development`) and enforce quality checks before merging pull requests. + +## 🎯 Why Set Up Branch Protection? + +- ✅ **Prevents Accidents**: No one can accidentally push directly to `main` +- ✅ **Enforces Reviews**: Requires code review before merging +- ✅ **Quality Gates**: Ensures all tests pass before merge +- ✅ **Maintains Workflow**: Enforces your development → main workflow +- ✅ **Audit Trail**: All changes go through documented PRs + +## 🔧 Setup Instructions + +### Step 1: Access Branch Protection Settings + +1. Go to your repository on GitHub: `https://github.com/nimritagames/Unity-FlowUI` +2. Click **Settings** (top menu) +3. Click **Branches** (left sidebar) +4. Under "Branch protection rules", click **Add rule** + +### Step 2: Protect `main` Branch + +#### Rule Configuration + +**Branch name pattern**: `main` + +#### Settings to Enable + +##### Protect matching branches +- ✅ **Require a pull request before merging** + - ✅ Require approvals: `1` (at least one approval) + - ✅ Dismiss stale pull request approvals when new commits are pushed + - ⬜ Require review from Code Owners (enable if you add CODEOWNERS file) + +- ✅ **Require status checks to pass before merging** + - ✅ Require branches to be up to date before merging + - **Add required status checks** (these will appear after first PR runs): + - `⚡ Quick Validation` + - `🧪 Unity Tests` + - `📝 Code Quality` + - `📋 PR Summary` + +- ✅ **Require conversation resolution before merging** + - Ensures all PR comments are addressed + +- ✅ **Require signed commits** (optional but recommended) + - Adds extra security verification + +- ✅ **Require linear history** + - Prevents merge commits, keeps history clean + +- ✅ **Include administrators** + - Even repo admins must follow these rules + +- ✅ **Restrict who can push to matching branches** + - Select specific users/teams who can merge (usually just maintainers) + - Or leave empty to allow all with approval + +- ✅ **Allow force pushes** → **DISABLE** + - Prevents destructive force pushes + +- ✅ **Allow deletions** → **DISABLE** + - Prevents accidental branch deletion + +#### Click "Create" to Save + +### Step 3: Protect `development` Branch + +Now repeat the process for the `development` branch: + +**Branch name pattern**: `development` + +#### Settings to Enable + +##### Protect matching branches +- ✅ **Require a pull request before merging** + - ✅ Require approvals: `1` + - ✅ Dismiss stale pull request approvals when new commits are pushed + +- ✅ **Require status checks to pass before merging** + - ✅ Require branches to be up to date before merging + - **Add required status checks**: + - `⚡ Quick Validation` + - `🧪 Unity Tests` + - `📝 Code Quality` + +- ✅ **Require conversation resolution before merging** + +- ✅ **Require linear history** + +- ✅ **Include administrators** + +- ✅ **Allow force pushes** → **DISABLE** + +- ✅ **Allow deletions** → **DISABLE** + +#### Click "Create" to Save + +## 📋 Summary of Protection Rules + +### `main` Branch +``` +✅ Requires PR with 1 approval +✅ All status checks must pass +✅ Branch must be up-to-date +✅ All conversations resolved +✅ Linear history (no merge commits) +✅ Applies to administrators +❌ No force pushes +❌ No deletions +``` + +### `development` Branch +``` +✅ Requires PR with 1 approval +✅ All status checks must pass +✅ Branch must be up-to-date +✅ All conversations resolved +✅ Linear history +✅ Applies to administrators +❌ No force pushes +❌ No deletions +``` + +## 🔄 Your Workflow After Setup + +### ✅ Allowed +```bash +# Create feature branch from development +git checkout development +git pull origin development +git checkout -b feature/my-feature + +# Make changes and commit +git add . +git commit -m "feat: Add new feature" +git push origin feature/my-feature + +# Create PR on GitHub: feature/my-feature → development +# After approval and checks pass, merge via GitHub UI +``` + +### ❌ Blocked (These will be prevented!) +```bash +# Direct push to main (BLOCKED!) +git checkout main +git commit -m "Direct commit" +git push origin main # ❌ ERROR: Protected branch + +# Direct push to development (BLOCKED!) +git checkout development +git commit -m "Direct commit" +git push origin development # ❌ ERROR: Protected branch + +# Force push (BLOCKED!) +git push --force origin main # ❌ ERROR: Force push not allowed +``` + +## 🎯 How to Work With Protection + +### Making Changes + +1. **Always work on feature branches** + ```bash + git checkout development + git checkout -b feature/my-new-feature + ``` + +2. **Push your feature branch** + ```bash + git push origin feature/my-new-feature + ``` + +3. **Create Pull Request on GitHub** + - Go to GitHub + - Click "New Pull Request" + - Base: `development` ← Compare: `feature/my-new-feature` + - Fill out PR template + - Submit for review + +4. **Wait for Checks and Approval** + - GitHub Actions will run automated tests + - Reviewer will approve (or request changes) + - All status checks must pass ✅ + +5. **Merge via GitHub UI** + - Once approved and checks pass, click "Merge Pull Request" + - Delete the feature branch after merge + +### Releasing to Main + +1. **Bump version in package.json** + ```bash + git checkout development + # Edit package.json, change version 1.0.0 → 1.1.0 + git add Packages/com.nimrita.flowui/package.json + git commit -m "chore: Bump version to 1.1.0" + git push origin development + ``` + +2. **Create PR: development → main** + - Go to GitHub + - Create PR from `development` to `main` + - Title: "Release v1.1.0" + - Wait for approval and checks + +3. **Merge and Release** + - Merge PR on GitHub + - GitHub Actions automatically creates release! + +## 🚨 Troubleshooting + +### "Push declined due to repository rule violations" + +**Cause**: You're trying to push directly to a protected branch. + +**Solution**: +```bash +# Create a feature branch instead +git checkout -b feature/my-changes + +# Push the feature branch +git push origin feature/my-changes + +# Then create a PR on GitHub +``` + +### "Required status check is expected" + +**Cause**: A required check hasn't run yet or failed. + +**Solution**: +- Wait for GitHub Actions to complete +- If checks fail, fix the issues and push again +- Check the Actions tab for details + +### "Review required before merging" + +**Cause**: No one has approved your PR yet. + +**Solution**: +- Wait for a maintainer to review +- Address any review feedback +- Once approved, you can merge + +### "Branch is out of date" + +**Cause**: The base branch has new commits since you created your PR. + +**Solution**: +```bash +# Update your feature branch +git checkout feature/my-feature +git fetch origin +git rebase origin/development # or origin/main + +# Force push (this is allowed on feature branches!) +git push --force-with-lease origin feature/my-feature +``` + +## 📚 Additional Resources + +- [GitHub Docs: Branch Protection](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches) +- [GitHub Docs: Status Checks](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks) +- [Contributing Guide](../CONTRIBUTING.md) - Your workflow documentation + +## ✅ Verification + +After setting up, verify the protection works: + +1. **Try to push to main directly** (should fail) + ```bash + git checkout main + echo "test" > test.txt + git add test.txt + git commit -m "test" + git push origin main # Should be blocked! + ``` + +2. **Create a test PR** + - Create a feature branch + - Push it + - Open PR to `development` + - Verify status checks run + - Verify you can't merge without approval + +If both work as expected, your branch protection is configured correctly! 🎉 + +--- + +**Need Help?** Open an issue on GitHub or ask in Discussions. diff --git a/docs/GITHUB_ACTIONS_GUIDE.md b/docs/GITHUB_ACTIONS_GUIDE.md new file mode 100644 index 0000000..d633cf4 --- /dev/null +++ b/docs/GITHUB_ACTIONS_GUIDE.md @@ -0,0 +1,618 @@ +# GitHub Actions CI/CD Learning Guide + +Welcome to your complete guide for understanding GitHub Actions and CI/CD for Unity packages! This guide will take you from zero to hero. 🚀 + +## Table of Contents + +- [What is CI/CD?](#what-is-cicd) +- [What is GitHub Actions?](#what-is-github-actions) +- [Understanding Our Workflows](#understanding-our-workflows) +- [Setting Up Unity License](#setting-up-unity-license) +- [Monitoring Workflows](#monitoring-workflows) +- [Troubleshooting](#troubleshooting) +- [Advanced Topics](#advanced-topics) + +## What is CI/CD? + +### CI - Continuous Integration + +**Continuous Integration** means automatically testing your code every time you make changes. + +**Example without CI:** +``` +1. You write code +2. You push to GitHub +3. Someone else pulls your code +4. Their Unity project breaks! 💥 +5. Hours wasted finding the bug +``` + +**Example with CI:** +``` +1. You write code +2. You push to GitHub +3. GitHub Actions automatically runs tests +4. You get instant feedback: ✅ Pass or ❌ Fail +5. Fix bugs BEFORE anyone else sees them! +``` + +### CD - Continuous Deployment/Delivery + +**Continuous Deployment** means automatically releasing your code when it's ready. + +**Example without CD:** +``` +1. You finish a feature +2. You manually create a release +3. You manually write changelog +4. You manually tag the version +5. You manually upload package +6. This takes 30+ minutes! 😓 +``` + +**Example with CD:** +``` +1. You finish a feature +2. Merge to main branch +3. GitHub Actions automatically: + - Creates release + - Generates changelog + - Tags version + - Uploads package +4. All in under 5 minutes! 🎉 +``` + +## What is GitHub Actions? + +GitHub Actions is GitHub's built-in automation system. Think of it as robots that work for you 24/7! + +### Key Concepts + +#### 1. Workflow +A workflow is a YAML file that defines automation tasks. + +**Location**: `.github/workflows/*.yml` + +**Example**: `development.yml` runs tests when you push code + +#### 2. Trigger (on:) +Defines WHEN the workflow runs. + +```yaml +on: + push: + branches: + - development # Run when pushing to development + pull_request: + branches: + - development # Run when creating PR to development +``` + +**Common Triggers:** +- `push` - When you push commits +- `pull_request` - When you create/update a PR +- `schedule` - Run on a schedule (e.g., daily) +- `workflow_dispatch` - Manual trigger from GitHub UI + +#### 3. Job +A job is a set of steps that run on the same machine. + +```yaml +jobs: + test-unity-package: # Job ID + name: 🧪 Run Unity Tests # Display name + runs-on: ubuntu-latest # What OS to use + steps: + # Steps go here +``` + +**Key Points:** +- Jobs run in PARALLEL by default (faster!) +- Each job gets a fresh virtual machine +- Jobs can depend on other jobs (`needs:`) + +#### 4. Step +A step is a single task within a job. + +```yaml +steps: + - name: 📥 Checkout Code + uses: actions/checkout@v4 # Use a pre-made action + + - name: 🎮 Run Tests + run: echo "Running tests" # Run a shell command +``` + +**Two Types of Steps:** +1. **Action** (`uses:`) - Pre-made reusable component +2. **Script** (`run:`) - Custom shell commands + +#### 5. Runner +A runner is the virtual machine that executes your workflow. + +**Available Runners:** +- `ubuntu-latest` - Linux (fastest, cheapest) +- `windows-latest` - Windows +- `macos-latest` - macOS + +**For Unity packages, use**: `ubuntu-latest` (required by GameCI) + +#### 6. Secrets +Secrets are encrypted environment variables for sensitive data. + +**Example:** +```yaml +env: + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + UNITY_SERIAL: ${{ secrets.UNITY_SERIAL }} +``` + +## Understanding Our Workflows + +### 1. Development Workflow (`development.yml`) + +**Purpose**: Run tests on every push to `development` branch + +**When it runs:** +- You push to `development` +- Someone creates a PR to `development` + +**What it does:** +1. ✅ Checks out your code +2. ✅ Caches Unity Library (for speed) +3. ✅ Runs Unity tests (EditMode + PlayMode) +4. ✅ Validates package.json +5. ✅ Checks required files exist +6. ✅ Uploads test results + +**Time**: ~2-5 minutes (first run: ~10 min, cached: ~2 min) + +**View Results**: GitHub Actions tab → "Development Branch Tests" + +### 2. Release Workflow (`release.yml`) + +**Purpose**: Automatically create releases when merging to `main` + +**When it runs:** +- You push to `main` (e.g., merge development → main) +- You push a version tag (e.g., `v1.0.0`) + +**What it does:** +1. ✅ Reads version from package.json +2. ✅ Generates changelog from commits +3. ✅ Creates GitHub release +4. ✅ Creates package .zip file +5. ✅ Uploads package to release +6. ✅ Updates CHANGELOG.md + +**Time**: ~1-2 minutes + +**Result**: Automatic release on GitHub! + +### 3. PR Checks Workflow (`pr-checks.yml`) + +**Purpose**: Quality gates before merging ANY pull request + +**When it runs:** +- Someone creates a PR +- New commits are pushed to PR + +**What it does:** +1. ⚡ **Quick Checks** (runs first, fast!) + - Validate package.json format + - Check version format + - Verify required files exist + - Check for .meta files + - Look for forbidden patterns + +2. 🧪 **Unity Tests** (runs after quick checks) + - Run all Unity tests + - Generate coverage report + - Post results as PR comment + +3. 📝 **Code Quality** + - Check C# naming conventions + - Validate assembly definitions + - Check for license headers + +4. 📋 **Summary** + - Overall pass/fail status + +**Time**: ~3-7 minutes + +**Result**: PR can only merge if ALL checks pass! + +## Setting Up Unity License + +GitHub Actions needs a Unity license to run your tests. Here's how to set it up: + +### Option 1: Personal License (Recommended for Open Source) + +#### Step 1: Get Activation File + +1. Create `.github/workflows/get-license.yml`: + ```yaml + name: Get Unity License + on: workflow_dispatch + jobs: + get-license: + runs-on: ubuntu-latest + steps: + - uses: game-ci/unity-request-activation-file@v2 + - uses: actions/upload-artifact@v3 + with: + name: Unity_v2022.3.alf + path: Unity_v2022.3.alf + ``` + +2. Push this file to GitHub +3. Go to Actions tab → "Get Unity License" → "Run workflow" +4. Download the `.alf` file from artifacts + +#### Step 2: Generate License File + +1. Go to https://license.unity3d.com/manual +2. Upload your `.alf` file +3. Select "Unity Personal" (free for open source) +4. Download the `.ulf` license file + +#### Step 3: Add to GitHub Secrets + +1. Open your `.ulf` file in a text editor +2. Copy the entire contents +3. Go to GitHub: Settings → Secrets and variables → Actions +4. Click "New repository secret" +5. Add these secrets: + - Name: `UNITY_LICENSE`, Value: [paste entire .ulf contents] + - Name: `UNITY_EMAIL`, Value: [your Unity email] + - Name: `UNITY_PASSWORD`, Value: [your Unity password] + - Name: `UNITY_SERIAL`, Value: [leave empty for Personal] + +#### Step 4: Update Workflows + +Your workflows are already configured! But verify they use: +```yaml +env: + UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }} + UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }} + UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }} +``` + +#### Step 5: Test + +1. Push a commit to `development` +2. Go to Actions tab +3. Watch your first workflow run! 🎉 + +### Option 2: Professional License + +If you have Unity Pro or Plus: + +1. Get your serial key from Unity Dashboard +2. Add to GitHub Secrets: + - Name: `UNITY_EMAIL`, Value: [your email] + - Name: `UNITY_PASSWORD`, Value: [your password] + - Name: `UNITY_SERIAL`, Value: [your serial key] + +3. Update workflows to use `UNITY_SERIAL` instead of `UNITY_LICENSE` + +### Troubleshooting License Issues + +**Error: "Invalid license"** +- Regenerate `.ulf` file +- Ensure entire `.ulf` contents copied to secret +- Check expiration date + +**Error: "Too many activations"** +- Unity Personal allows 2 activations +- Deactivate old builds: Unity Hub → Preferences → Licenses → Deactivate + +**Error: "License expired"** +- Personal licenses expire yearly +- Regenerate following Step 1-3 above + +## Monitoring Workflows + +### Where to View Workflows + +1. **GitHub Repository** → **Actions tab** +2. You'll see: + - Workflow runs (left sidebar) + - Run history (main area) + - Status badges (✅ passing, ❌ failing) + +### Understanding Workflow Status + +#### ✅ Success +``` +✅ Development Branch Tests + All tests passed! Code is good to merge. +``` + +#### ❌ Failure +``` +❌ Development Branch Tests + Some tests failed. Click to see details. +``` + +#### 🟡 In Progress +``` +🟡 Development Branch Tests + Workflow is currently running... +``` + +#### ⚫ Cancelled +``` +⚫ Development Branch Tests + Workflow was cancelled (newer run started) +``` + +### Viewing Detailed Logs + +1. Click on a workflow run +2. Click on a job (e.g., "🧪 Run Unity Tests") +3. Expand steps to see detailed logs +4. Look for red ❌ marks indicating errors + +### Downloading Artifacts + +Some workflows save files (test results, coverage reports): + +1. Go to workflow run +2. Scroll to "Artifacts" section +3. Click to download (e.g., "Test Results.zip") + +## Troubleshooting + +### Common Issues + +#### 1. "Unity test runner failed" + +**Symptoms:** +``` +Error: Test execution failed with exit code 1 +``` + +**Causes:** +- Test failures in your code +- Unity version mismatch +- Missing dependencies + +**Solutions:** +1. Run tests locally first: Unity → Window → General → Test Runner +2. Check Unity version matches workflow (2022.3) +3. View detailed logs in Actions tab +4. Fix failing tests and push again + +#### 2. "Package validation failed" + +**Symptoms:** +``` +Error: Missing required files +``` + +**Causes:** +- Missing package.json +- Missing .asmdef files +- Missing .meta files + +**Solutions:** +1. Check `.github/workflows/development.yml` → "Check Required Files" +2. Ensure all required files exist +3. Commit missing files + +#### 3. "Workflow doesn't trigger" + +**Symptoms:** +- Push code but workflow doesn't run + +**Causes:** +- Wrong branch (workflow set for `development`, you pushed to `main`) +- Workflow file syntax error +- `.github/workflows/` path incorrect + +**Solutions:** +1. Check you pushed to correct branch +2. Validate YAML syntax: https://www.yamllint.com/ +3. Verify path: `.github/workflows/development.yml` (exactly this!) + +#### 4. "Cache restore failed" + +**Symptoms:** +``` +Warning: Cache restore failed +``` + +**Causes:** +- First run (no cache yet) +- Cache expired (7 days) +- Cache key changed + +**Solutions:** +- This is usually just a warning, not an error +- First run will be slower, future runs cached +- Ignore if workflow still completes + +#### 5. "API rate limit exceeded" + +**Symptoms:** +``` +Error: API rate limit exceeded +``` + +**Causes:** +- Too many workflow runs in short time +- GitHub API limits reached + +**Solutions:** +- Wait 1 hour for reset +- Use `concurrency:` to cancel old runs +- Reduce workflow frequency + +### Getting Help + +1. **Check Workflow Logs** - Most issues show clear error messages +2. **Search Issues** - Look for similar problems in GameCI issues +3. **Ask in Discussions** - Community can help! +4. **Read Documentation** - Links in [Resources](#resources) + +## Advanced Topics + +### Caching for Speed + +**What is caching?** +Caching saves the Unity Library folder between runs, making subsequent runs much faster. + +**How it works:** +```yaml +- uses: actions/cache@v3 + with: + path: Library # What to cache + key: Library-${{ hashFiles('package.json') }} # Cache key + restore-keys: Library- # Fallback if exact match not found +``` + +**Cache invalidation:** +- If `package.json` changes, cache is rebuilt +- Caches expire after 7 days of no use +- Manual: Settings → Actions → Caches → Delete + +### Matrix Builds (Testing Multiple Versions) + +Test against multiple Unity versions: + +```yaml +strategy: + matrix: + unity-version: + - 2022.3 + - 2023.1 + - 2023.2 + +steps: + - uses: game-ci/unity-test-runner@v4 + with: + unityVersion: ${{ matrix.unity-version }} +``` + +This creates 3 jobs, one for each version! + +### Conditional Steps + +Run steps only in certain conditions: + +```yaml +# Only on main branch +- name: Deploy + if: github.ref == 'refs/heads/main' + run: echo "Deploying..." + +# Only if tests passed +- name: Upload Coverage + if: success() + uses: actions/upload-artifact@v3 + +# Only if tests failed +- name: Notify Failure + if: failure() + run: echo "Tests failed!" + +# Always run (even if previous failed) +- name: Cleanup + if: always() + run: echo "Cleaning up..." +``` + +### Workflow Dispatch (Manual Triggers) + +Add manual trigger button: + +```yaml +on: + workflow_dispatch: # Adds "Run workflow" button in UI + inputs: + unity-version: + description: 'Unity version to use' + required: true + default: '2022.3' + +jobs: + manual-test: + runs-on: ubuntu-latest + steps: + - run: echo "Testing with Unity ${{ inputs.unity-version }}" +``` + +### Environment Variables + +**Set for entire workflow:** +```yaml +env: + UNITY_VERSION: 2022.3 + PACKAGE_NAME: com.nimrita.flowui + +jobs: + test: + steps: + - run: echo $UNITY_VERSION # Uses workflow-level env +``` + +**Set for specific job:** +```yaml +jobs: + test: + env: + TEST_MODE: all + steps: + - run: echo $TEST_MODE # Uses job-level env +``` + +**Set for specific step:** +```yaml +steps: + - name: Test + env: + LOG_LEVEL: debug + run: echo $LOG_LEVEL # Uses step-level env +``` + +### Status Badges + +Add status badges to your README: + +```markdown +[![Tests](https://github.com/nimritagames/Unity-FlowUI/actions/workflows/development.yml/badge.svg)](https://github.com/nimritagames/Unity-FlowUI/actions/workflows/development.yml) +``` + +Result: ![Tests](https://img.shields.io/badge/tests-passing-brightgreen) + +## Resources + +### Official Documentation +- [GitHub Actions Docs](https://docs.github.com/en/actions) +- [GameCI Documentation](https://game.ci/docs/github/getting-started) +- [Unity Test Framework](https://docs.unity3d.com/Packages/com.unity.test-framework@latest) + +### Useful Actions +- [actions/checkout](https://github.com/actions/checkout) - Check out repository +- [actions/cache](https://github.com/actions/cache) - Cache dependencies +- [actions/upload-artifact](https://github.com/actions/upload-artifact) - Upload files +- [game-ci/unity-test-runner](https://github.com/game-ci/unity-test-runner) - Run Unity tests + +### Learning Resources +- [GitHub Actions Tutorial](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions) +- [GameCI Getting Started](https://game.ci/docs/github/getting-started) +- [YAML Syntax Guide](https://learnxinyminutes.com/docs/yaml/) + +## Next Steps + +1. ✅ Set up Unity license (see above) +2. ✅ Push a commit and watch your first workflow run +3. ✅ Set up branch protection (see BRANCH_PROTECTION_SETUP.md) +4. ✅ Create your first pull request +5. ✅ Make your first release! + +--- + +**Questions?** Open an issue or discussion on GitHub! Happy automating! 🚀