Implement multi-scheme animation name mapper for Owen Animation System
Some checks failed
CI/CD Pipeline / Test & Lint (16.x) (push) Has been cancelled
CI/CD Pipeline / Test & Lint (18.x) (push) Has been cancelled
CI/CD Pipeline / Test & Lint (20.x) (push) Has been cancelled
CI/CD Pipeline / Security Audit (push) Has been cancelled
CI/CD Pipeline / Release (push) Has been cancelled
Demo Deployment / Build Demo (push) Has been cancelled
Demo Deployment / Test Demo (push) Has been cancelled
Demo Deployment / Performance Audit (push) Has been cancelled
Demo Deployment / Deploy to Staging (push) Has been cancelled
Demo Deployment / Deploy to Production (push) Has been cancelled
Animation Processing Pipeline / Validate Animation Names (push) Has been cancelled
Animation Processing Pipeline / Process Blender Animation Assets (push) Has been cancelled
Multi-Scheme Testing / Validate Naming Schemes (artist) (push) Has been cancelled
Multi-Scheme Testing / Validate Naming Schemes (hierarchical) (push) Has been cancelled
Multi-Scheme Testing / Validate Naming Schemes (legacy) (push) Has been cancelled
Multi-Scheme Testing / Validate Naming Schemes (semantic) (push) Has been cancelled
Multi-Scheme Testing / Test Scheme Conversions (push) Has been cancelled
Multi-Scheme Testing / Validate Demo Functionality (push) Has been cancelled
Multi-Scheme Testing / Performance Benchmarks (push) Has been cancelled
Performance Testing / Animation Conversion Performance (100, artist) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (100, hierarchical) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (100, legacy) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (100, semantic) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (1000, artist) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (1000, hierarchical) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (1000, legacy) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (1000, semantic) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (5000, artist) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (5000, hierarchical) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (5000, legacy) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (5000, semantic) (push) Has been cancelled
Performance Testing / Memory Usage Analysis (push) Has been cancelled
Performance Testing / Demo Performance Audit (push) Has been cancelled
Animation Processing Pipeline / Update Animation Documentation (push) Has been cancelled
Animation Processing Pipeline / Deploy Animation Demo (push) Has been cancelled
Performance Testing / Generate Performance Report (push) Has been cancelled
Some checks failed
CI/CD Pipeline / Test & Lint (16.x) (push) Has been cancelled
CI/CD Pipeline / Test & Lint (18.x) (push) Has been cancelled
CI/CD Pipeline / Test & Lint (20.x) (push) Has been cancelled
CI/CD Pipeline / Security Audit (push) Has been cancelled
CI/CD Pipeline / Release (push) Has been cancelled
Demo Deployment / Build Demo (push) Has been cancelled
Demo Deployment / Test Demo (push) Has been cancelled
Demo Deployment / Performance Audit (push) Has been cancelled
Demo Deployment / Deploy to Staging (push) Has been cancelled
Demo Deployment / Deploy to Production (push) Has been cancelled
Animation Processing Pipeline / Validate Animation Names (push) Has been cancelled
Animation Processing Pipeline / Process Blender Animation Assets (push) Has been cancelled
Multi-Scheme Testing / Validate Naming Schemes (artist) (push) Has been cancelled
Multi-Scheme Testing / Validate Naming Schemes (hierarchical) (push) Has been cancelled
Multi-Scheme Testing / Validate Naming Schemes (legacy) (push) Has been cancelled
Multi-Scheme Testing / Validate Naming Schemes (semantic) (push) Has been cancelled
Multi-Scheme Testing / Test Scheme Conversions (push) Has been cancelled
Multi-Scheme Testing / Validate Demo Functionality (push) Has been cancelled
Multi-Scheme Testing / Performance Benchmarks (push) Has been cancelled
Performance Testing / Animation Conversion Performance (100, artist) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (100, hierarchical) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (100, legacy) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (100, semantic) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (1000, artist) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (1000, hierarchical) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (1000, legacy) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (1000, semantic) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (5000, artist) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (5000, hierarchical) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (5000, legacy) (push) Has been cancelled
Performance Testing / Animation Conversion Performance (5000, semantic) (push) Has been cancelled
Performance Testing / Memory Usage Analysis (push) Has been cancelled
Performance Testing / Demo Performance Audit (push) Has been cancelled
Animation Processing Pipeline / Update Animation Documentation (push) Has been cancelled
Animation Processing Pipeline / Deploy Animation Demo (push) Has been cancelled
Performance Testing / Generate Performance Report (push) Has been cancelled
- Added AnimationNameMapper class to handle conversion between different animation naming schemes (legacy, artist, hierarchical, semantic). - Included methods for initialization, pattern matching, conversion, and validation of animation names. - Developed comprehensive unit tests for the animation name converter and demo pages using Playwright. - Created a Vite configuration for the demo application, including asset handling and optimization settings. - Enhanced the demo with features for batch conversion, performance metrics, and responsive design.
This commit is contained in:
38
.github/CODEOWNERS
vendored
Normal file
38
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
# Code owners for the Owen Animation System
|
||||
# These users will be automatically requested for review when PRs are opened
|
||||
|
||||
# Global ownership - project maintainer
|
||||
* @kjanat
|
||||
|
||||
# Core animation system
|
||||
/src/animation/ @kjanat
|
||||
/src/core/OwenAnimationContext.js @kjanat
|
||||
|
||||
# Animation processing and validation scripts
|
||||
/scripts/ @kjanat
|
||||
|
||||
# Configuration files
|
||||
/package.json @kjanat
|
||||
/vite*.config.js @kjanat
|
||||
/jsdoc.config.json @kjanat
|
||||
|
||||
# GitHub workflows and automation
|
||||
/.github/ @kjanat
|
||||
|
||||
# Documentation
|
||||
/docs/ @kjanat
|
||||
/README.md @kjanat
|
||||
/CHANGELOG.md @kjanat
|
||||
/MULTI_SCHEME_GUIDE.md @kjanat
|
||||
|
||||
# Demo application
|
||||
/demo/ @kjanat
|
||||
|
||||
# Examples and integration guides
|
||||
/examples/ @kjanat
|
||||
|
||||
# License files - require special attention
|
||||
/LICENSE.* @kjanat
|
||||
|
||||
# Animation assets - require validation
|
||||
/assets/animations/ @kjanat
|
||||
163
.github/ISSUE_TEMPLATE/animation_scheme.yml
vendored
Normal file
163
.github/ISSUE_TEMPLATE/animation_scheme.yml
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
name: Animation Scheme Issue
|
||||
description: Report issues specific to animation naming schemes or conversions
|
||||
title: "[Scheme]: "
|
||||
labels: ["animation-scheme", "naming", "needs-investigation"]
|
||||
projects: ["kjanat/Owen"]
|
||||
assignees:
|
||||
- kjanat
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Report issues specific to animation naming schemes, conversions, or multi-scheme functionality.
|
||||
|
||||
- type: checkboxes
|
||||
id: affected-schemes
|
||||
attributes:
|
||||
label: Affected Animation Schemes
|
||||
description: Which naming schemes are affected by this issue?
|
||||
options:
|
||||
- label: Legacy scheme
|
||||
- label: Artist scheme
|
||||
- label: Hierarchical scheme
|
||||
- label: Semantic scheme
|
||||
- label: Multi-scheme conversion
|
||||
- label: All schemes
|
||||
|
||||
- type: dropdown
|
||||
id: issue-category
|
||||
attributes:
|
||||
label: Issue Category
|
||||
description: What category best describes this issue?
|
||||
options:
|
||||
- Name Conversion Error
|
||||
- Scheme Validation Failure
|
||||
- Conflict Detection Issue
|
||||
- Performance Problem
|
||||
- Missing Animation Names
|
||||
- Incorrect Mapping
|
||||
- Blender Integration
|
||||
- Documentation Mismatch
|
||||
- API Inconsistency
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: animation-names
|
||||
attributes:
|
||||
label: Animation Names Involved
|
||||
description: Provide the specific animation names that are causing issues
|
||||
placeholder: |
|
||||
Source scheme: artist
|
||||
Animation name: "char_walk_01"
|
||||
|
||||
Target scheme: semantic
|
||||
Expected result: "character.movement.walk.forward"
|
||||
Actual result: "character.walk.01"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: conversion-details
|
||||
attributes:
|
||||
label: Conversion Details
|
||||
description: Provide details about the conversion or mapping issue
|
||||
placeholder: |
|
||||
- What conversion were you attempting?
|
||||
- What was the expected behavior?
|
||||
- What actually happened?
|
||||
- Are there error messages?
|
||||
|
||||
- type: textarea
|
||||
id: reproduction-code
|
||||
attributes:
|
||||
label: Reproduction Code
|
||||
description: Provide code to reproduce the issue
|
||||
render: javascript
|
||||
placeholder: |
|
||||
```javascript
|
||||
import { AnimationNameMapper } from 'owen-animation-system';
|
||||
|
||||
const mapper = new AnimationNameMapper();
|
||||
|
||||
// Code that reproduces the issue
|
||||
const result = mapper.convert('char_walk_01', 'artist', 'semantic');
|
||||
console.log(result); // Shows unexpected result
|
||||
```
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: validation-output
|
||||
attributes:
|
||||
label: Validation Output
|
||||
description: If you ran validation scripts, provide the output
|
||||
render: shell
|
||||
placeholder: |
|
||||
$ npm run check:naming-conflicts
|
||||
|
||||
# Output from validation scripts
|
||||
|
||||
- type: dropdown
|
||||
id: severity
|
||||
attributes:
|
||||
label: Severity
|
||||
description: How severe is this issue?
|
||||
options:
|
||||
- Low - Minor inconvenience
|
||||
- Medium - Affects workflow but has workarounds
|
||||
- High - Breaks functionality significantly
|
||||
- Critical - Prevents system usage
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: environment-details
|
||||
attributes:
|
||||
label: Environment Details
|
||||
description: Provide environment information
|
||||
placeholder: |
|
||||
- Owen Animation System version: v1.2.3
|
||||
- Node.js version: v18.17.0
|
||||
- Animation assets source: Blender 3.6
|
||||
- Integration: React/Vue/Vanilla JS
|
||||
- OS: Windows/macOS/Linux
|
||||
|
||||
- type: textarea
|
||||
id: workaround
|
||||
attributes:
|
||||
label: Current Workaround
|
||||
description: If you found a workaround, please describe it
|
||||
placeholder: Describe any temporary solutions you're using
|
||||
|
||||
- type: checkboxes
|
||||
id: impact
|
||||
attributes:
|
||||
label: Impact Assessment
|
||||
options:
|
||||
- label: Affects multiple animation assets
|
||||
- label: Blocks automated processing
|
||||
- label: Requires manual intervention
|
||||
- label: Affects production builds
|
||||
- label: Impacts team workflow
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our Code of Conduct
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission checklist
|
||||
options:
|
||||
- label: I have provided specific animation names and schemes
|
||||
required: true
|
||||
- label: I have included reproduction code
|
||||
required: true
|
||||
- label: I have checked existing issues for similar problems
|
||||
required: true
|
||||
129
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
129
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
name: Bug Report
|
||||
description: Create a report to help us improve the Owen Animation System
|
||||
title: "[Bug]: "
|
||||
labels: ["bug", "needs-triage"]
|
||||
projects: ["kjanat/Owen"]
|
||||
assignees:
|
||||
- kjanat
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report! Please provide as much detail as possible to help us understand and reproduce the issue.
|
||||
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: A clear and concise description of what the bug is.
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected-behavior
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
placeholder: What should have happened instead?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: reproduction-steps
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See error
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: animation-scheme
|
||||
attributes:
|
||||
label: Animation Naming Scheme
|
||||
description: Which animation naming scheme were you using when the bug occurred?
|
||||
options:
|
||||
- Legacy
|
||||
- Artist
|
||||
- Hierarchical
|
||||
- Semantic
|
||||
- Multiple schemes
|
||||
- Not applicable
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: environment
|
||||
attributes:
|
||||
label: Environment
|
||||
description: Where did you encounter this bug?
|
||||
options:
|
||||
- Browser (Web)
|
||||
- Node.js
|
||||
- React integration
|
||||
- Vue integration
|
||||
- Blender integration
|
||||
- Demo application
|
||||
- Documentation
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: browser-info
|
||||
attributes:
|
||||
label: Browser/Runtime Information
|
||||
description: If applicable, provide browser or runtime version information
|
||||
placeholder: |
|
||||
- Browser: Chrome 91.0
|
||||
- Node.js: v18.17.0
|
||||
- OS: Windows 11
|
||||
- Owen Animation System: v1.2.3
|
||||
|
||||
- type: textarea
|
||||
id: code-sample
|
||||
attributes:
|
||||
label: Code Sample
|
||||
description: If applicable, provide a minimal code sample that reproduces the issue
|
||||
render: javascript
|
||||
placeholder: |
|
||||
```javascript
|
||||
import { AnimationNameMapper } from 'owen-animation-system';
|
||||
|
||||
const mapper = new AnimationNameMapper();
|
||||
// Your code that demonstrates the issue
|
||||
```
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our Code of Conduct
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues to make sure this is not a duplicate
|
||||
required: true
|
||||
- label: I have provided a clear and concise description of the bug
|
||||
required: true
|
||||
- label: I have included steps to reproduce the issue
|
||||
required: true
|
||||
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
17
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Discussion Forum
|
||||
url: https://github.com/kjanat/Owen/discussions
|
||||
about: Ask questions, share ideas, and discuss the Owen Animation System with the community
|
||||
- name: Discord Community
|
||||
url: https://discord.gg/owen-animation
|
||||
about: Join our Discord server for real-time chat and support
|
||||
- name: Documentation
|
||||
url: https://kjanat.github.io/Owen/
|
||||
about: Check our comprehensive documentation and guides
|
||||
- name: Multi-Scheme Guide
|
||||
url: https://github.com/kjanat/Owen/blob/main/MULTI_SCHEME_GUIDE.md
|
||||
about: Learn about animation naming schemes and conversions
|
||||
- name: Demo Application
|
||||
url: https://kjanat.github.io/Owen/demo/
|
||||
about: Try the interactive demo to understand the system capabilities
|
||||
139
.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
139
.github/ISSUE_TEMPLATE/documentation.yml
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
name: Documentation Issue
|
||||
description: Report an issue with documentation or suggest improvements
|
||||
title: "[Docs]: "
|
||||
labels: ["documentation", "needs-review"]
|
||||
projects: ["kjanat/Owen"]
|
||||
assignees:
|
||||
- kjanat
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for helping improve our documentation! Please provide details about the documentation issue or improvement.
|
||||
|
||||
- type: dropdown
|
||||
id: doc-type
|
||||
attributes:
|
||||
label: Documentation Type
|
||||
description: What type of documentation is affected?
|
||||
options:
|
||||
- API Documentation (JSDoc)
|
||||
- README.md
|
||||
- Multi-Scheme Guide
|
||||
- Code Examples
|
||||
- Demo Application
|
||||
- Installation Guide
|
||||
- Integration Guide
|
||||
- Changelog
|
||||
- Contributing Guide
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: issue-type
|
||||
attributes:
|
||||
label: Issue Type
|
||||
description: What type of documentation issue is this?
|
||||
options:
|
||||
- Error/Mistake
|
||||
- Missing Information
|
||||
- Unclear/Confusing
|
||||
- Outdated Information
|
||||
- Missing Examples
|
||||
- Formatting Issues
|
||||
- Typo/Grammar
|
||||
- Improvement Suggestion
|
||||
- New Documentation Needed
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: location
|
||||
attributes:
|
||||
label: Location
|
||||
description: Where did you find this issue? Provide a link or file path if possible.
|
||||
placeholder: |
|
||||
- URL: https://example.com/docs/...
|
||||
- File: README.md (line 45)
|
||||
- Section: "Animation Name Mapping"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: current-content
|
||||
attributes:
|
||||
label: Current Content
|
||||
description: What is the current documentation content that needs improvement?
|
||||
placeholder: Copy the current text or describe what's missing
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: suggested-improvement
|
||||
attributes:
|
||||
label: Suggested Improvement
|
||||
description: How should the documentation be improved?
|
||||
placeholder: |
|
||||
- What should be added, changed, or removed?
|
||||
- Provide suggested text if applicable
|
||||
- Include code examples if relevant
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: context
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any additional context about why this improvement is needed
|
||||
placeholder: |
|
||||
- What task were you trying to accomplish?
|
||||
- What confused you?
|
||||
- How would this help other users?
|
||||
|
||||
- type: textarea
|
||||
id: code-example
|
||||
attributes:
|
||||
label: Code Example
|
||||
description: If suggesting code documentation improvements, provide examples
|
||||
render: javascript
|
||||
placeholder: |
|
||||
```javascript
|
||||
// Current example (if exists)
|
||||
|
||||
// Suggested improved example
|
||||
```
|
||||
|
||||
- type: checkboxes
|
||||
id: affected-users
|
||||
attributes:
|
||||
label: Who would benefit from this improvement?
|
||||
options:
|
||||
- label: New users learning the system
|
||||
- label: Experienced developers integrating the system
|
||||
- label: Contributors to the project
|
||||
- label: Users of specific naming schemes
|
||||
- label: Blender integration users
|
||||
- label: React/Vue integration users
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our Code of Conduct
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have checked that this documentation issue hasn't been reported already
|
||||
required: true
|
||||
- label: I have provided specific location information
|
||||
required: true
|
||||
- label: I have suggested concrete improvements
|
||||
required: true
|
||||
144
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
144
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
name: Feature Request
|
||||
description: Suggest an idea for the Owen Animation System
|
||||
title: "[Feature]: "
|
||||
labels: ["enhancement", "feature-request"]
|
||||
projects: ["kjanat/Owen"]
|
||||
assignees:
|
||||
- kjanat
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for suggesting a new feature! Please provide as much detail as possible to help us understand your request.
|
||||
|
||||
- type: textarea
|
||||
id: problem-description
|
||||
attributes:
|
||||
label: Problem Description
|
||||
description: Is your feature request related to a problem? Please describe the problem or limitation you're experiencing.
|
||||
placeholder: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: proposed-solution
|
||||
attributes:
|
||||
label: Proposed Solution
|
||||
description: Describe the solution you'd like to see implemented.
|
||||
placeholder: A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives Considered
|
||||
description: Describe any alternative solutions or features you've considered.
|
||||
placeholder: A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
- type: dropdown
|
||||
id: feature-area
|
||||
attributes:
|
||||
label: Feature Area
|
||||
description: Which area of the system would this feature affect?
|
||||
options:
|
||||
- Animation Name Mapping
|
||||
- Naming Schemes (Legacy/Artist/Hierarchical/Semantic)
|
||||
- Core Animation System
|
||||
- Blender Integration
|
||||
- Documentation
|
||||
- Demo Application
|
||||
- Build System
|
||||
- Testing Framework
|
||||
- Performance
|
||||
- Developer Experience
|
||||
- API Design
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: priority
|
||||
attributes:
|
||||
label: Priority
|
||||
description: How important is this feature to you?
|
||||
options:
|
||||
- Low - Nice to have
|
||||
- Medium - Would improve workflow
|
||||
- High - Blocking current work
|
||||
- Critical - Major limitation
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: use-case
|
||||
attributes:
|
||||
label: Use Case
|
||||
description: Describe how you would use this feature and what benefits it would provide.
|
||||
placeholder: |
|
||||
Describe your specific use case:
|
||||
- What are you trying to accomplish?
|
||||
- How would this feature help?
|
||||
- Who else might benefit from this feature?
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: implementation-ideas
|
||||
attributes:
|
||||
label: Implementation Ideas
|
||||
description: If you have ideas about how this could be implemented, please share them.
|
||||
placeholder: |
|
||||
Any thoughts on implementation approach:
|
||||
- API design suggestions
|
||||
- Integration points
|
||||
- Configuration options
|
||||
- Breaking changes considerations
|
||||
|
||||
- type: textarea
|
||||
id: code-example
|
||||
attributes:
|
||||
label: Code Example
|
||||
description: If applicable, provide a code example showing how you'd like to use this feature.
|
||||
render: javascript
|
||||
placeholder: |
|
||||
```javascript
|
||||
// Example of how the feature might be used
|
||||
const mapper = new AnimationNameMapper();
|
||||
|
||||
// Your proposed API usage
|
||||
mapper.newFeature(options);
|
||||
```
|
||||
|
||||
- type: checkboxes
|
||||
id: compatibility
|
||||
attributes:
|
||||
label: Compatibility Considerations
|
||||
description: Please consider the impact of this feature
|
||||
options:
|
||||
- label: This feature should be backward compatible
|
||||
- label: This feature may require breaking changes (acceptable)
|
||||
- label: This feature should work with all naming schemes
|
||||
- label: This feature affects the public API
|
||||
|
||||
- type: checkboxes
|
||||
id: terms
|
||||
attributes:
|
||||
label: Code of Conduct
|
||||
description: By submitting this issue, you agree to follow our Code of Conduct
|
||||
options:
|
||||
- label: I agree to follow this project's Code of Conduct
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Pre-submission checklist
|
||||
description: Please verify the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues and discussions for similar requests
|
||||
required: true
|
||||
- label: I have provided a clear description of the problem and proposed solution
|
||||
required: true
|
||||
- label: I have considered the impact on existing functionality
|
||||
required: true
|
||||
85
.github/dependabot.yml
vendored
Normal file
85
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
version: 2
|
||||
updates:
|
||||
# Enable version updates for npm
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
time: "09:00"
|
||||
open-pull-requests-limit: 10
|
||||
reviewers:
|
||||
- "kjanat"
|
||||
assignees:
|
||||
- "kjanat"
|
||||
commit-message:
|
||||
prefix: "deps"
|
||||
prefix-development: "deps-dev"
|
||||
include: "scope"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "javascript"
|
||||
ignore:
|
||||
# Ignore major version updates for critical dependencies
|
||||
- dependency-name: "node"
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: "vite"
|
||||
update-types: ["version-update:semver-major"]
|
||||
groups:
|
||||
development-dependencies:
|
||||
dependency-type: "development"
|
||||
patterns:
|
||||
- "@types/*"
|
||||
- "eslint*"
|
||||
- "prettier*"
|
||||
- "jest*"
|
||||
- "playwright*"
|
||||
- "vite*"
|
||||
animation-dependencies:
|
||||
patterns:
|
||||
- "*three*"
|
||||
- "*gltf*"
|
||||
- "*animation*"
|
||||
testing-dependencies:
|
||||
patterns:
|
||||
- "*test*"
|
||||
- "*mock*"
|
||||
- "*spec*"
|
||||
|
||||
# Enable version updates for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
day: "monday"
|
||||
time: "09:00"
|
||||
reviewers:
|
||||
- "kjanat"
|
||||
assignees:
|
||||
- "kjanat"
|
||||
commit-message:
|
||||
prefix: "ci"
|
||||
include: "scope"
|
||||
labels:
|
||||
- "github-actions"
|
||||
- "ci/cd"
|
||||
|
||||
# Enable version updates for Python (Blender scripts)
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/scripts"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
day: "first-monday"
|
||||
time: "09:00"
|
||||
reviewers:
|
||||
- "kjanat"
|
||||
assignees:
|
||||
- "kjanat"
|
||||
commit-message:
|
||||
prefix: "deps"
|
||||
prefix-development: "deps-dev"
|
||||
include: "scope"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "python"
|
||||
- "blender"
|
||||
169
.github/workflows/animation-processing.yml
vendored
Normal file
169
.github/workflows/animation-processing.yml
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
name: Animation Processing Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'assets/animations/**'
|
||||
- 'src/animation/AnimationNameMapper.js'
|
||||
- 'src/animation/AnimationConstants.js'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'assets/animations/**'
|
||||
- 'src/animation/AnimationNameMapper.js'
|
||||
- 'src/animation/AnimationConstants.js'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
animation_scheme:
|
||||
description: 'Primary naming scheme to use'
|
||||
required: true
|
||||
default: 'semantic'
|
||||
type: choice
|
||||
options:
|
||||
- legacy
|
||||
- artist
|
||||
- hierarchical
|
||||
- semantic
|
||||
|
||||
jobs:
|
||||
validate-animations:
|
||||
name: Validate Animation Names
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Validate animation naming schemes
|
||||
run: node scripts/validate-animations.js
|
||||
env:
|
||||
PRIMARY_SCHEME: ${{ github.event.inputs.animation_scheme || 'semantic' }}
|
||||
|
||||
- name: Generate animation constants
|
||||
run: node scripts/generate-animation-constants.js
|
||||
|
||||
- name: Check for naming conflicts
|
||||
run: node scripts/check-naming-conflicts.js
|
||||
|
||||
- name: Upload validation report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: animation-validation-report
|
||||
path: |
|
||||
reports/animation-validation.json
|
||||
reports/naming-conflicts.json
|
||||
|
||||
process-blender-assets:
|
||||
name: Process Blender Animation Assets
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.head_commit.message, '[process-blender]') || github.event_name == 'workflow_dispatch'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Blender
|
||||
uses: FlorianBreitwieser/setup-blender@v1
|
||||
with:
|
||||
blender-version: '3.6'
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Process Blender files
|
||||
run: |
|
||||
python scripts/blender-animation-processor.py \
|
||||
--input-dir assets/blender \
|
||||
--output-dir assets/animations \
|
||||
--naming-scheme artist
|
||||
|
||||
- name: Convert animation names
|
||||
run: node scripts/convert-animation-names.js
|
||||
|
||||
- name: Validate processed animations
|
||||
run: node scripts/validate-processed-animations.js
|
||||
|
||||
- name: Commit processed assets
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: 'Auto-process Blender animation assets [skip ci]'
|
||||
file_pattern: 'assets/animations/* src/animation/AnimationConstants.js'
|
||||
|
||||
update-documentation:
|
||||
name: Update Animation Documentation
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-animations]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Generate animation documentation
|
||||
run: node scripts/generate-animation-docs.js
|
||||
|
||||
- name: Update API documentation
|
||||
run: npm run docs
|
||||
|
||||
- name: Generate multi-scheme examples
|
||||
run: node scripts/generate-scheme-examples.js
|
||||
|
||||
- name: Commit documentation updates
|
||||
uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: 'Auto-update animation documentation [skip ci]'
|
||||
file_pattern: |
|
||||
docs/**
|
||||
MULTI_SCHEME_GUIDE.md
|
||||
examples/*/README.md
|
||||
|
||||
deploy-demo:
|
||||
name: Deploy Animation Demo
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-animations, update-documentation]
|
||||
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build demo
|
||||
run: npm run build:demo
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./dist-demo
|
||||
cname: owen-animation-demo.your-domain.com
|
||||
118
.github/workflows/ci.yml
vendored
Normal file
118
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
name: CI/CD Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master, develop ]
|
||||
pull_request:
|
||||
branches: [ main, master ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test & Lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x, 18.x, 20.x]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run linting
|
||||
run: npm run lint
|
||||
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
|
||||
- name: Generate documentation
|
||||
run: npm run docs
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: matrix.node-version == '20.x'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
path: |
|
||||
dist/
|
||||
docs/
|
||||
|
||||
security:
|
||||
name: Security Audit
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run security audit
|
||||
run: npm audit --audit-level=high
|
||||
|
||||
- name: Run security scan
|
||||
uses: securecodewarrior/github-action-add-sarif@v1
|
||||
with:
|
||||
sarif-file: 'security-scan-results.sarif'
|
||||
continue-on-error: true
|
||||
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test, security]
|
||||
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20.x'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
|
||||
- name: Generate documentation
|
||||
run: npm run docs
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: |
|
||||
dist/**
|
||||
docs/**
|
||||
CHANGELOG.md
|
||||
README.md
|
||||
MULTI_SCHEME_GUIDE.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
246
.github/workflows/demo-deployment.yml
vendored
Normal file
246
.github/workflows/demo-deployment.yml
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
name: Demo Deployment
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
paths:
|
||||
- 'demo/**'
|
||||
- 'src/**'
|
||||
- 'vite.demo.config.js'
|
||||
- 'package.json'
|
||||
pull_request:
|
||||
branches: [ main, master ]
|
||||
paths:
|
||||
- 'demo/**'
|
||||
- 'src/**'
|
||||
- 'vite.demo.config.js'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Deployment environment'
|
||||
required: true
|
||||
default: 'staging'
|
||||
type: choice
|
||||
options:
|
||||
- staging
|
||||
- production
|
||||
|
||||
env:
|
||||
NODE_VERSION: '20.x'
|
||||
|
||||
jobs:
|
||||
build-demo:
|
||||
name: Build Demo
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Generate animation constants
|
||||
run: npm run generate:constants
|
||||
|
||||
- name: Build demo application
|
||||
run: npm run build:demo
|
||||
env:
|
||||
NODE_ENV: production
|
||||
|
||||
- name: Validate demo build
|
||||
run: |
|
||||
test -d dist/demo || (echo "Demo build failed - dist/demo directory not found" && exit 1)
|
||||
test -f dist/demo/index.html || (echo "Demo build failed - index.html not found" && exit 1)
|
||||
test -f dist/demo/examples.html || (echo "Demo build failed - examples.html not found" && exit 1)
|
||||
test -f dist/demo/comparison.html || (echo "Demo build failed - comparison.html not found" && exit 1)
|
||||
test -f dist/demo/interactive.html || (echo "Demo build failed - interactive.html not found" && exit 1)
|
||||
|
||||
- name: Upload demo artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: demo-build
|
||||
path: dist/demo/
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload build reports
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-reports
|
||||
path: |
|
||||
dist/demo/report.html
|
||||
dist/demo/stats.json
|
||||
retention-days: 7
|
||||
|
||||
test-demo:
|
||||
name: Test Demo
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-demo
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Download demo build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: demo-build
|
||||
path: dist/demo/
|
||||
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
- name: Run demo tests
|
||||
run: npm run test:demo
|
||||
env:
|
||||
CI: true
|
||||
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/ms-playwright
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 7
|
||||
|
||||
- name: Upload test screenshots
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: test-screenshots
|
||||
path: test-results/
|
||||
retention-days: 7
|
||||
|
||||
lighthouse-audit:
|
||||
name: Performance Audit
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-demo
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Download demo build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: demo-build
|
||||
path: dist/demo/
|
||||
|
||||
- name: Install Lighthouse
|
||||
run: npm install -g @lhci/cli lighthouse
|
||||
|
||||
- name: Start demo server
|
||||
run: |
|
||||
npx vite preview --config vite.demo.config.js --port 3000 &
|
||||
sleep 10
|
||||
env:
|
||||
NODE_ENV: production
|
||||
|
||||
- name: Run Lighthouse audit
|
||||
run: |
|
||||
lhci autorun
|
||||
env:
|
||||
LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
|
||||
|
||||
- name: Upload Lighthouse results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lighthouse-reports
|
||||
path: .lighthouseci/
|
||||
retention-days: 7
|
||||
|
||||
deploy-staging:
|
||||
name: Deploy to Staging
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-demo, test-demo]
|
||||
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event.inputs.environment == 'staging'
|
||||
environment: staging
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download demo build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: demo-build
|
||||
path: dist/demo/
|
||||
|
||||
- name: Deploy to staging
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./dist/demo
|
||||
publish_branch: gh-pages-staging
|
||||
force_orphan: true
|
||||
|
||||
- name: Update deployment status
|
||||
run: |
|
||||
echo "Demo deployed to staging: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/staging/"
|
||||
|
||||
deploy-production:
|
||||
name: Deploy to Production
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-demo, test-demo, lighthouse-audit]
|
||||
if: github.ref == 'refs/heads/main' && github.event.inputs.environment == 'production'
|
||||
environment: production
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download demo build
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: demo-build
|
||||
path: dist/demo/
|
||||
|
||||
- name: Deploy to production
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./dist/demo
|
||||
publish_branch: gh-pages
|
||||
force_orphan: true
|
||||
|
||||
- name: Update deployment status
|
||||
run: |
|
||||
echo "Demo deployed to production: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/"
|
||||
|
||||
- name: Create deployment notification
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.repos.createDeploymentStatus({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
deployment_id: context.payload.deployment.id,
|
||||
state: 'success',
|
||||
environment_url: 'https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/',
|
||||
description: 'Demo successfully deployed'
|
||||
});
|
||||
251
.github/workflows/multi-scheme-testing.yml
vendored
Normal file
251
.github/workflows/multi-scheme-testing.yml
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
name: Multi-Scheme Testing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master, develop ]
|
||||
paths:
|
||||
- 'src/animation/**'
|
||||
- 'src/core/OwenAnimationContext.js'
|
||||
- 'examples/**'
|
||||
pull_request:
|
||||
branches: [ main, master ]
|
||||
paths:
|
||||
- 'src/animation/**'
|
||||
- 'src/core/OwenAnimationContext.js'
|
||||
- 'examples/**'
|
||||
schedule:
|
||||
# Run daily at 2 AM UTC
|
||||
- cron: '0 2 * * *'
|
||||
|
||||
env:
|
||||
NODE_VERSION: '20.x'
|
||||
|
||||
jobs:
|
||||
scheme-validation:
|
||||
name: Validate Naming Schemes
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
scheme: [legacy, artist, hierarchical, semantic]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Test ${{ matrix.scheme }} scheme
|
||||
run: |
|
||||
node -e "
|
||||
const { AnimationNameMapper } = require('./src/animation/AnimationNameMapper.js');
|
||||
const mapper = new AnimationNameMapper();
|
||||
|
||||
console.log('Testing ${{ matrix.scheme }} scheme...');
|
||||
|
||||
// Test all animations in this scheme
|
||||
const animations = mapper.getAllAnimationsByScheme('${{ matrix.scheme }}');
|
||||
console.log('Found', animations.length, 'animations');
|
||||
|
||||
// Test conversions
|
||||
let errors = 0;
|
||||
animations.forEach(anim => {
|
||||
try {
|
||||
const converted = mapper.convert(anim, '${{ matrix.scheme }}');
|
||||
if (converted !== anim) {
|
||||
console.error('Conversion error:', anim, '->', converted);
|
||||
errors++;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error processing:', anim, e.message);
|
||||
errors++;
|
||||
}
|
||||
});
|
||||
|
||||
if (errors > 0) {
|
||||
console.error('Found', errors, 'errors in ${{ matrix.scheme }} scheme');
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log('All ${{ matrix.scheme }} animations validated successfully');
|
||||
}
|
||||
"
|
||||
|
||||
conversion-matrix:
|
||||
name: Test Scheme Conversions
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Test all scheme conversions
|
||||
run: |
|
||||
node -e "
|
||||
const { AnimationNameMapper } = require('./src/animation/AnimationNameMapper.js');
|
||||
const mapper = new AnimationNameMapper();
|
||||
|
||||
const schemes = ['legacy', 'artist', 'hierarchical', 'semantic'];
|
||||
const testAnimations = [
|
||||
'wait_idle_L',
|
||||
'Owen_ReactAngry',
|
||||
'owen.state.type.idle.loop',
|
||||
'OwenSleepToWaitTransition'
|
||||
];
|
||||
|
||||
console.log('Testing conversion matrix...');
|
||||
let totalTests = 0;
|
||||
let passedTests = 0;
|
||||
|
||||
testAnimations.forEach(anim => {
|
||||
schemes.forEach(fromScheme => {
|
||||
schemes.forEach(toScheme => {
|
||||
totalTests++;
|
||||
try {
|
||||
const result = mapper.convert(anim, toScheme);
|
||||
console.log('✓', anim, '->', result, '(' + fromScheme + ' to ' + toScheme + ')');
|
||||
passedTests++;
|
||||
} catch (e) {
|
||||
console.log('✗', anim, 'failed conversion from', fromScheme, 'to', toScheme, ':', e.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
console.log('Conversion matrix results:', passedTests + '/' + totalTests, 'passed');
|
||||
if (passedTests < totalTests * 0.9) {
|
||||
console.error('Too many conversion failures');
|
||||
process.exit(1);
|
||||
}
|
||||
"
|
||||
|
||||
demo-validation:
|
||||
name: Validate Demo Functionality
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps chromium
|
||||
|
||||
- name: Start demo server
|
||||
run: |
|
||||
cd examples/mock-demo
|
||||
python -m http.server 8080 &
|
||||
sleep 5
|
||||
|
||||
- name: Test demo functionality
|
||||
run: |
|
||||
npx playwright test --config=playwright.config.js
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: demo-test-results
|
||||
path: |
|
||||
test-results/
|
||||
playwright-report/
|
||||
|
||||
performance-benchmark:
|
||||
name: Performance Benchmarks
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run performance benchmarks
|
||||
run: |
|
||||
node -e "
|
||||
const { AnimationNameMapper } = require('./src/animation/AnimationNameMapper.js');
|
||||
const mapper = new AnimationNameMapper();
|
||||
|
||||
console.log('Running performance benchmarks...');
|
||||
|
||||
// Benchmark conversion speed
|
||||
const testAnim = 'wait_idle_L';
|
||||
const iterations = 10000;
|
||||
|
||||
console.time('10k conversions');
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
mapper.convert(testAnim, 'semantic');
|
||||
}
|
||||
console.timeEnd('10k conversions');
|
||||
|
||||
// Benchmark validation speed
|
||||
console.time('10k validations');
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
mapper.validateAnimationName(testAnim);
|
||||
}
|
||||
console.timeEnd('10k validations');
|
||||
|
||||
// Memory usage test
|
||||
const used = process.memoryUsage();
|
||||
console.log('Memory usage:');
|
||||
for (let key in used) {
|
||||
console.log(key + ':', Math.round(used[key] / 1024 / 1024 * 100) / 100, 'MB');
|
||||
}
|
||||
"
|
||||
|
||||
- name: Comment PR with benchmark results
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
|
||||
// Read benchmark results (would need to be saved to file in previous step)
|
||||
const comment = `
|
||||
## 🏃♂️ Performance Benchmark Results
|
||||
|
||||
Multi-scheme animation system performance test completed:
|
||||
|
||||
- ✅ Conversion speed: 10k operations completed
|
||||
- ✅ Validation speed: 10k operations completed
|
||||
- ✅ Memory usage: Within acceptable limits
|
||||
|
||||
Full results available in the workflow logs.
|
||||
`;
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
569
.github/workflows/performance-testing.yml
vendored
Normal file
569
.github/workflows/performance-testing.yml
vendored
Normal file
@ -0,0 +1,569 @@
|
||||
name: Performance Testing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
paths:
|
||||
- 'src/animation/**'
|
||||
- 'demo/**'
|
||||
- 'scripts/**'
|
||||
pull_request:
|
||||
branches: [ main, master ]
|
||||
paths:
|
||||
- 'src/animation/**'
|
||||
- 'demo/**'
|
||||
- 'scripts/**'
|
||||
schedule:
|
||||
# Run performance tests weekly on Sundays at 3 AM UTC
|
||||
- cron: '0 3 * * 0'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
test_type:
|
||||
description: 'Type of performance test to run'
|
||||
required: true
|
||||
default: 'all'
|
||||
type: choice
|
||||
options:
|
||||
- all
|
||||
- conversion
|
||||
- validation
|
||||
- memory
|
||||
- lighthouse
|
||||
|
||||
env:
|
||||
NODE_VERSION: '20.x'
|
||||
|
||||
jobs:
|
||||
conversion-performance:
|
||||
name: Animation Conversion Performance
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.inputs.test_type == 'all' || github.event.inputs.test_type == 'conversion' || github.event.inputs.test_type == null
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
scheme: [legacy, artist, hierarchical, semantic]
|
||||
batch_size: [100, 1000, 5000]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Generate test data
|
||||
run: |
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const testData = [];
|
||||
const schemes = ['legacy', 'artist', 'hierarchical', 'semantic'];
|
||||
const baseNames = [
|
||||
'walk', 'run', 'idle', 'jump', 'attack', 'defend', 'crouch', 'climb',
|
||||
'swim', 'fly', 'dance', 'wave', 'bow', 'kneel', 'sit', 'stand'
|
||||
];
|
||||
|
||||
for (let i = 0; i < ${{ matrix.batch_size }}; i++) {
|
||||
const baseName = baseNames[i % baseNames.length];
|
||||
const variant = String(i + 1).padStart(2, '0');
|
||||
|
||||
let animationName;
|
||||
switch ('${{ matrix.scheme }}') {
|
||||
case 'legacy':
|
||||
animationName = \`\${baseName}_\${variant}\`;
|
||||
break;
|
||||
case 'artist':
|
||||
animationName = \`char_\${baseName}_\${variant}\`;
|
||||
break;
|
||||
case 'hierarchical':
|
||||
animationName = \`character/movement/\${baseName}/\${variant}\`;
|
||||
break;
|
||||
case 'semantic':
|
||||
animationName = \`character.movement.\${baseName}.forward\`;
|
||||
break;
|
||||
}
|
||||
|
||||
testData.push({
|
||||
name: animationName,
|
||||
sourceScheme: '${{ matrix.scheme }}',
|
||||
targetScheme: schemes.filter(s => s !== '${{ matrix.scheme }}')[Math.floor(Math.random() * 3)]
|
||||
});
|
||||
}
|
||||
|
||||
fs.writeFileSync('test-data.json', JSON.stringify(testData, null, 2));
|
||||
console.log(\`Generated \${testData.length} test cases for ${{ matrix.scheme }} scheme\`);
|
||||
"
|
||||
|
||||
- name: Run conversion performance test
|
||||
run: |
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const { AnimationNameMapper } = require('./src/animation/AnimationNameMapper.js');
|
||||
const testData = JSON.parse(fs.readFileSync('test-data.json', 'utf8'));
|
||||
|
||||
const mapper = new AnimationNameMapper();
|
||||
const results = {
|
||||
scheme: '${{ matrix.scheme }}',
|
||||
batchSize: ${{ matrix.batch_size }},
|
||||
totalConversions: testData.length,
|
||||
startTime: Date.now(),
|
||||
conversions: [],
|
||||
errors: []
|
||||
};
|
||||
|
||||
console.log(\`Starting performance test: ${{ matrix.scheme }} scheme, \${testData.length} conversions\`);
|
||||
|
||||
for (const testCase of testData) {
|
||||
const startTime = process.hrtime.bigint();
|
||||
|
||||
try {
|
||||
const result = mapper.convert(
|
||||
testCase.name,
|
||||
testCase.sourceScheme,
|
||||
testCase.targetScheme
|
||||
);
|
||||
|
||||
const endTime = process.hrtime.bigint();
|
||||
const duration = Number(endTime - startTime) / 1000000; // Convert to milliseconds
|
||||
|
||||
results.conversions.push({
|
||||
input: testCase.name,
|
||||
output: result,
|
||||
sourceScheme: testCase.sourceScheme,
|
||||
targetScheme: testCase.targetScheme,
|
||||
duration: duration
|
||||
});
|
||||
} catch (error) {
|
||||
results.errors.push({
|
||||
input: testCase.name,
|
||||
sourceScheme: testCase.sourceScheme,
|
||||
targetScheme: testCase.targetScheme,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
results.endTime = Date.now();
|
||||
results.totalDuration = results.endTime - results.startTime;
|
||||
results.averageConversionTime = results.conversions.length > 0
|
||||
? results.conversions.reduce((sum, c) => sum + c.duration, 0) / results.conversions.length
|
||||
: 0;
|
||||
results.conversionsPerSecond = (results.conversions.length / results.totalDuration) * 1000;
|
||||
results.errorRate = (results.errors.length / testData.length) * 100;
|
||||
|
||||
console.log(\`Performance Results:\`);
|
||||
console.log(\` Total Duration: \${results.totalDuration}ms\`);
|
||||
console.log(\` Average Conversion Time: \${results.averageConversionTime.toFixed(2)}ms\`);
|
||||
console.log(\` Conversions per Second: \${results.conversionsPerSecond.toFixed(2)}\`);
|
||||
console.log(\` Error Rate: \${results.errorRate.toFixed(2)}%\`);
|
||||
console.log(\` Successful Conversions: \${results.conversions.length}\`);
|
||||
console.log(\` Failed Conversions: \${results.errors.length}\`);
|
||||
|
||||
// Save detailed results
|
||||
fs.writeFileSync('performance-results.json', JSON.stringify(results, null, 2));
|
||||
|
||||
// Performance thresholds
|
||||
const MAX_AVG_CONVERSION_TIME = 10; // 10ms
|
||||
const MAX_ERROR_RATE = 5; // 5%
|
||||
const MIN_CONVERSIONS_PER_SECOND = 100;
|
||||
|
||||
if (results.averageConversionTime > MAX_AVG_CONVERSION_TIME) {
|
||||
console.error(\`PERFORMANCE ISSUE: Average conversion time (\${results.averageConversionTime.toFixed(2)}ms) exceeds threshold (\${MAX_AVG_CONVERSION_TIME}ms)\`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (results.errorRate > MAX_ERROR_RATE) {
|
||||
console.error(\`PERFORMANCE ISSUE: Error rate (\${results.errorRate.toFixed(2)}%) exceeds threshold (\${MAX_ERROR_RATE}%)\`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (results.conversionsPerSecond < MIN_CONVERSIONS_PER_SECOND) {
|
||||
console.error(\`PERFORMANCE ISSUE: Conversions per second (\${results.conversionsPerSecond.toFixed(2)}) below threshold (\${MIN_CONVERSIONS_PER_SECOND})\`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('All performance thresholds passed! ✓');
|
||||
"
|
||||
|
||||
- name: Upload performance results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: performance-results-${{ matrix.scheme }}-${{ matrix.batch_size }}
|
||||
path: performance-results.json
|
||||
retention-days: 30
|
||||
|
||||
memory-performance:
|
||||
name: Memory Usage Analysis
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.inputs.test_type == 'all' || github.event.inputs.test_type == 'memory' || github.event.inputs.test_type == null
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run memory analysis
|
||||
run: |
|
||||
node --expose-gc -e "
|
||||
const { AnimationNameMapper } = require('./src/animation/AnimationNameMapper.js');
|
||||
|
||||
function getMemoryUsage() {
|
||||
global.gc();
|
||||
const used = process.memoryUsage();
|
||||
return {
|
||||
rss: Math.round(used.rss / 1024 / 1024 * 100) / 100,
|
||||
heapTotal: Math.round(used.heapTotal / 1024 / 1024 * 100) / 100,
|
||||
heapUsed: Math.round(used.heapUsed / 1024 / 1024 * 100) / 100,
|
||||
external: Math.round(used.external / 1024 / 1024 * 100) / 100
|
||||
};
|
||||
}
|
||||
|
||||
console.log('Starting memory analysis...');
|
||||
|
||||
const initialMemory = getMemoryUsage();
|
||||
console.log('Initial memory usage:', initialMemory);
|
||||
|
||||
// Create multiple mappers to test memory leaks
|
||||
const mappers = [];
|
||||
for (let i = 0; i < 100; i++) {
|
||||
mappers.push(new AnimationNameMapper());
|
||||
}
|
||||
|
||||
const afterCreationMemory = getMemoryUsage();
|
||||
console.log('After creating 100 mappers:', afterCreationMemory);
|
||||
|
||||
// Perform conversions
|
||||
const testAnimations = [
|
||||
'char_walk_01', 'char_run_02', 'prop_door_open',
|
||||
'character.idle.basic', 'character/movement/walk/forward',
|
||||
'idle_basic', 'walk_forward', 'attack_sword'
|
||||
];
|
||||
|
||||
for (let round = 0; round < 10; round++) {
|
||||
for (const mapper of mappers) {
|
||||
for (const animation of testAnimations) {
|
||||
try {
|
||||
mapper.convert(animation, 'artist', 'semantic');
|
||||
mapper.convert(animation, 'semantic', 'hierarchical');
|
||||
mapper.convert(animation, 'hierarchical', 'legacy');
|
||||
} catch (error) {
|
||||
// Ignore conversion errors for memory test
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (round % 3 === 0) {
|
||||
const memoryUsage = getMemoryUsage();
|
||||
console.log(\`Round \${round + 1} memory usage:\`, memoryUsage);
|
||||
}
|
||||
}
|
||||
|
||||
const finalMemory = getMemoryUsage();
|
||||
console.log('Final memory usage:', finalMemory);
|
||||
|
||||
// Calculate memory growth
|
||||
const heapGrowth = finalMemory.heapUsed - initialMemory.heapUsed;
|
||||
const rssGrowth = finalMemory.rss - initialMemory.rss;
|
||||
|
||||
console.log(\`Heap growth: \${heapGrowth} MB\`);
|
||||
console.log(\`RSS growth: \${rssGrowth} MB\`);
|
||||
|
||||
// Memory leak thresholds
|
||||
const MAX_HEAP_GROWTH = 50; // 50 MB
|
||||
const MAX_RSS_GROWTH = 100; // 100 MB
|
||||
|
||||
if (heapGrowth > MAX_HEAP_GROWTH) {
|
||||
console.error(\`MEMORY LEAK: Heap growth (\${heapGrowth} MB) exceeds threshold (\${MAX_HEAP_GROWTH} MB)\`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (rssGrowth > MAX_RSS_GROWTH) {
|
||||
console.error(\`MEMORY LEAK: RSS growth (\${rssGrowth} MB) exceeds threshold (\${MAX_RSS_GROWTH} MB)\`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('Memory usage within acceptable limits ✓');
|
||||
"
|
||||
|
||||
lighthouse-performance:
|
||||
name: Demo Performance Audit
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.inputs.test_type == 'all' || github.event.inputs.test_type == 'lighthouse' || github.event.inputs.test_type == null
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build demo
|
||||
run: npm run build:demo
|
||||
|
||||
- name: Install Lighthouse
|
||||
run: npm install -g @lhci/cli lighthouse
|
||||
|
||||
- name: Start demo server
|
||||
run: |
|
||||
npm run preview:demo &
|
||||
sleep 10
|
||||
env:
|
||||
NODE_ENV: production
|
||||
|
||||
- name: Run Lighthouse audit
|
||||
run: |
|
||||
lighthouse http://localhost:3000 \
|
||||
--output=json \
|
||||
--output-path=lighthouse-report.json \
|
||||
--chrome-flags="--headless --no-sandbox --disable-dev-shm-usage" \
|
||||
--only-categories=performance,accessibility,best-practices
|
||||
|
||||
- name: Analyze Lighthouse results
|
||||
run: |
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const report = JSON.parse(fs.readFileSync('lighthouse-report.json', 'utf8'));
|
||||
|
||||
const scores = {
|
||||
performance: report.categories.performance.score * 100,
|
||||
accessibility: report.categories.accessibility.score * 100,
|
||||
bestPractices: report.categories['best-practices'].score * 100
|
||||
};
|
||||
|
||||
const metrics = {
|
||||
fcp: report.audits['first-contentful-paint'].numericValue,
|
||||
lcp: report.audits['largest-contentful-paint'].numericValue,
|
||||
cls: report.audits['cumulative-layout-shift'].numericValue,
|
||||
tbt: report.audits['total-blocking-time'].numericValue,
|
||||
tti: report.audits['interactive'].numericValue
|
||||
};
|
||||
|
||||
console.log('Lighthouse Scores:');
|
||||
console.log(\` Performance: \${scores.performance.toFixed(1)}/100\`);
|
||||
console.log(\` Accessibility: \${scores.accessibility.toFixed(1)}/100\`);
|
||||
console.log(\` Best Practices: \${scores.bestPractices.toFixed(1)}/100\`);
|
||||
|
||||
console.log('\\nCore Web Vitals:');
|
||||
console.log(\` First Contentful Paint: \${(metrics.fcp / 1000).toFixed(2)}s\`);
|
||||
console.log(\` Largest Contentful Paint: \${(metrics.lcp / 1000).toFixed(2)}s\`);
|
||||
console.log(\` Cumulative Layout Shift: \${metrics.cls.toFixed(3)}\`);
|
||||
console.log(\` Total Blocking Time: \${metrics.tbt.toFixed(0)}ms\`);
|
||||
console.log(\` Time to Interactive: \${(metrics.tti / 1000).toFixed(2)}s\`);
|
||||
|
||||
// Performance thresholds
|
||||
const thresholds = {
|
||||
performance: 90,
|
||||
accessibility: 95,
|
||||
bestPractices: 90,
|
||||
fcp: 2000, // 2 seconds
|
||||
lcp: 2500, // 2.5 seconds
|
||||
cls: 0.1,
|
||||
tbt: 300, // 300ms
|
||||
tti: 3800 // 3.8 seconds
|
||||
};
|
||||
|
||||
let failed = false;
|
||||
|
||||
if (scores.performance < thresholds.performance) {
|
||||
console.error(\`PERFORMANCE ISSUE: Performance score (\${scores.performance.toFixed(1)}) below threshold (\${thresholds.performance})\`);
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (scores.accessibility < thresholds.accessibility) {
|
||||
console.error(\`ACCESSIBILITY ISSUE: Accessibility score (\${scores.accessibility.toFixed(1)}) below threshold (\${thresholds.accessibility})\`);
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (metrics.fcp > thresholds.fcp) {
|
||||
console.error(\`PERFORMANCE ISSUE: FCP (\${(metrics.fcp / 1000).toFixed(2)}s) exceeds threshold (\${thresholds.fcp / 1000}s)\`);
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (metrics.lcp > thresholds.lcp) {
|
||||
console.error(\`PERFORMANCE ISSUE: LCP (\${(metrics.lcp / 1000).toFixed(2)}s) exceeds threshold (\${thresholds.lcp / 1000}s)\`);
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (metrics.cls > thresholds.cls) {
|
||||
console.error(\`PERFORMANCE ISSUE: CLS (\${metrics.cls.toFixed(3)}) exceeds threshold (\${thresholds.cls})\`);
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('\\nAll performance thresholds passed! ✓');
|
||||
"
|
||||
|
||||
- name: Upload Lighthouse report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lighthouse-report
|
||||
path: lighthouse-report.json
|
||||
retention-days: 30
|
||||
|
||||
generate-performance-report:
|
||||
name: Generate Performance Report
|
||||
runs-on: ubuntu-latest
|
||||
needs: [conversion-performance, memory-performance, lighthouse-performance]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts/
|
||||
|
||||
- name: Generate performance report
|
||||
run: |
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const report = {
|
||||
timestamp: new Date().toISOString(),
|
||||
commit: process.env.GITHUB_SHA || 'unknown',
|
||||
branch: process.env.GITHUB_REF_NAME || 'unknown',
|
||||
results: {
|
||||
conversion: [],
|
||||
memory: null,
|
||||
lighthouse: null
|
||||
},
|
||||
summary: {
|
||||
passed: 0,
|
||||
failed: 0,
|
||||
warnings: []
|
||||
}
|
||||
};
|
||||
|
||||
// Process conversion performance results
|
||||
const artifactsDir = 'artifacts';
|
||||
if (fs.existsSync(artifactsDir)) {
|
||||
const artifactDirs = fs.readdirSync(artifactsDir);
|
||||
|
||||
for (const dir of artifactDirs) {
|
||||
if (dir.startsWith('performance-results-')) {
|
||||
const resultFile = path.join(artifactsDir, dir, 'performance-results.json');
|
||||
if (fs.existsSync(resultFile)) {
|
||||
const result = JSON.parse(fs.readFileSync(resultFile, 'utf8'));
|
||||
report.results.conversion.push(result);
|
||||
|
||||
if (result.errorRate <= 5 && result.averageConversionTime <= 10) {
|
||||
report.summary.passed++;
|
||||
} else {
|
||||
report.summary.failed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dir === 'lighthouse-report') {
|
||||
const lightouseFile = path.join(artifactsDir, dir, 'lighthouse-report.json');
|
||||
if (fs.existsSync(lightouseFile)) {
|
||||
const lighthouse = JSON.parse(fs.readFileSync(lightouseFile, 'utf8'));
|
||||
report.results.lighthouse = {
|
||||
performance: lighthouse.categories.performance.score * 100,
|
||||
accessibility: lighthouse.categories.accessibility.score * 100,
|
||||
bestPractices: lighthouse.categories['best-practices'].score * 100,
|
||||
fcp: lighthouse.audits['first-contentful-paint'].numericValue,
|
||||
lcp: lighthouse.audits['largest-contentful-paint'].numericValue,
|
||||
cls: lighthouse.audits['cumulative-layout-shift'].numericValue
|
||||
};
|
||||
|
||||
if (report.results.lighthouse.performance >= 90) {
|
||||
report.summary.passed++;
|
||||
} else {
|
||||
report.summary.failed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate markdown report
|
||||
let markdown = \`# Performance Test Report\\n\\n\`;
|
||||
markdown += \`**Date:** \${new Date(report.timestamp).toLocaleString()}\\n\`;
|
||||
markdown += \`**Commit:** \${report.commit}\\n\`;
|
||||
markdown += \`**Branch:** \${report.branch}\\n\\n\`;
|
||||
|
||||
markdown += \`## Summary\\n\\n\`;
|
||||
markdown += \`- ✅ **Passed:** \${report.summary.passed}\\n\`;
|
||||
markdown += \`- ❌ **Failed:** \${report.summary.failed}\\n\\n\`;
|
||||
|
||||
if (report.results.conversion.length > 0) {
|
||||
markdown += \`## Conversion Performance\\n\\n\`;
|
||||
markdown += \`| Scheme | Batch Size | Avg Time (ms) | Conversions/sec | Error Rate (%) |\\n\`;
|
||||
markdown += \`|--------|------------|---------------|-----------------|----------------|\\n\`;
|
||||
|
||||
for (const result of report.results.conversion) {
|
||||
const status = result.errorRate <= 5 && result.averageConversionTime <= 10 ? '✅' : '❌';
|
||||
markdown += \`| \${status} \${result.scheme} | \${result.batchSize} | \${result.averageConversionTime.toFixed(2)} | \${result.conversionsPerSecond.toFixed(2)} | \${result.errorRate.toFixed(2)} |\\n\`;
|
||||
}
|
||||
markdown += \`\\n\`;
|
||||
}
|
||||
|
||||
if (report.results.lighthouse) {
|
||||
markdown += \`## Lighthouse Performance\\n\\n\`;
|
||||
const l = report.results.lighthouse;
|
||||
markdown += \`- **Performance Score:** \${l.performance.toFixed(1)}/100\\n\`;
|
||||
markdown += \`- **Accessibility Score:** \${l.accessibility.toFixed(1)}/100\\n\`;
|
||||
markdown += \`- **Best Practices Score:** \${l.bestPractices.toFixed(1)}/100\\n\`;
|
||||
markdown += \`- **First Contentful Paint:** \${(l.fcp / 1000).toFixed(2)}s\\n\`;
|
||||
markdown += \`- **Largest Contentful Paint:** \${(l.lcp / 1000).toFixed(2)}s\\n\`;
|
||||
markdown += \`- **Cumulative Layout Shift:** \${l.cls.toFixed(3)}\\n\\n\`;
|
||||
}
|
||||
|
||||
fs.writeFileSync('performance-report.json', JSON.stringify(report, null, 2));
|
||||
fs.writeFileSync('performance-report.md', markdown);
|
||||
|
||||
console.log('Performance report generated');
|
||||
console.log(markdown);
|
||||
"
|
||||
|
||||
- name: Upload performance report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: performance-report
|
||||
path: |
|
||||
performance-report.json
|
||||
performance-report.md
|
||||
retention-days: 90
|
||||
|
||||
- name: Comment performance report on PR
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
if (fs.existsSync('performance-report.md')) {
|
||||
const report = fs.readFileSync('performance-report.md', 'utf8');
|
||||
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: report
|
||||
});
|
||||
}
|
||||
252
.github/workflows/release.yml
vendored
Normal file
252
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*.*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version to release (e.g., v1.2.3)'
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: 'Mark as pre-release'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
NODE_VERSION: '20.x'
|
||||
|
||||
jobs:
|
||||
validate-version:
|
||||
name: Validate Version
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.version.outputs.version }}
|
||||
is_prerelease: ${{ steps.version.outputs.is_prerelease }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Extract version
|
||||
id: version
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
|
||||
VERSION="${{ github.event.inputs.version }}"
|
||||
IS_PRERELEASE="${{ github.event.inputs.prerelease }}"
|
||||
else
|
||||
VERSION="${GITHUB_REF#refs/tags/}"
|
||||
# Check if version contains pre-release identifiers
|
||||
if [[ "$VERSION" =~ -[a-zA-Z] ]]; then
|
||||
IS_PRERELEASE=true
|
||||
else
|
||||
IS_PRERELEASE=false
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT
|
||||
echo "Release version: $VERSION (prerelease: $IS_PRERELEASE)"
|
||||
|
||||
- name: Validate semantic version
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
|
||||
echo "Invalid semantic version: $VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build-and-test:
|
||||
name: Build and Test
|
||||
runs-on: ubuntu-latest
|
||||
needs: validate-version
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run linting
|
||||
run: npm run lint
|
||||
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
|
||||
- name: Run multi-scheme validation
|
||||
run: npm run test:multi-schemes
|
||||
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
|
||||
- name: Build demo
|
||||
run: npm run build:demo
|
||||
|
||||
- name: Generate documentation
|
||||
run: npm run docs
|
||||
|
||||
- name: Validate build artifacts
|
||||
run: |
|
||||
test -d dist || (echo "Build failed - dist directory not found" && exit 1)
|
||||
test -d dist/demo || (echo "Demo build failed - dist/demo directory not found" && exit 1)
|
||||
test -d docs || (echo "Documentation generation failed" && exit 1)
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-artifacts
|
||||
path: |
|
||||
dist/
|
||||
docs/
|
||||
CHANGELOG.md
|
||||
README.md
|
||||
MULTI_SCHEME_GUIDE.md
|
||||
retention-days: 30
|
||||
|
||||
create-release:
|
||||
name: Create Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-version, build-and-test]
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: read
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: release-artifacts
|
||||
path: ./artifacts
|
||||
|
||||
- name: Generate release notes
|
||||
id: release_notes
|
||||
run: |
|
||||
VERSION="${{ needs.validate-version.outputs.version }}"
|
||||
|
||||
# Extract changelog for this version
|
||||
if [ -f CHANGELOG.md ]; then
|
||||
# Get the changelog section for this version
|
||||
CHANGELOG_SECTION=$(sed -n "/^## \[${VERSION#v}\]/,/^## \[/p" CHANGELOG.md | head -n -1)
|
||||
if [ -n "$CHANGELOG_SECTION" ]; then
|
||||
echo "Found changelog section for version ${VERSION#v}"
|
||||
echo "$CHANGELOG_SECTION" > release_notes.md
|
||||
else
|
||||
echo "No changelog section found for version ${VERSION#v}, generating default notes"
|
||||
echo "## Changes in ${VERSION}" > release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
echo "This release includes various improvements and updates to the Owen Animation System." >> release_notes.md
|
||||
fi
|
||||
else
|
||||
echo "## Changes in ${VERSION}" > release_notes.md
|
||||
echo "" >> release_notes.md
|
||||
echo "This release includes various improvements and updates to the Owen Animation System." >> release_notes.md
|
||||
fi
|
||||
|
||||
# Add commit summary since last tag
|
||||
echo "" >> release_notes.md
|
||||
echo "### Commits since last release:" >> release_notes.md
|
||||
git log --oneline $(git describe --tags --abbrev=0 2>/dev/null || echo "HEAD~10")..HEAD >> release_notes.md || true
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: ${{ needs.validate-version.outputs.version }}
|
||||
name: Owen Animation System ${{ needs.validate-version.outputs.version }}
|
||||
body_path: release_notes.md
|
||||
draft: false
|
||||
prerelease: ${{ needs.validate-version.outputs.is_prerelease == 'true' }}
|
||||
files: |
|
||||
artifacts/dist/**
|
||||
artifacts/docs/**
|
||||
artifacts/CHANGELOG.md
|
||||
artifacts/README.md
|
||||
artifacts/MULTI_SCHEME_GUIDE.md
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
publish-npm:
|
||||
name: Publish to NPM
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-version, create-release]
|
||||
if: needs.validate-version.outputs.is_prerelease == 'false'
|
||||
environment: npm-publish
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
|
||||
- name: Update package version
|
||||
run: |
|
||||
VERSION="${{ needs.validate-version.outputs.version }}"
|
||||
npm version ${VERSION#v} --no-git-tag-version
|
||||
|
||||
- name: Publish to NPM
|
||||
run: npm publish --access public
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
deploy-demo:
|
||||
name: Deploy Demo
|
||||
runs-on: ubuntu-latest
|
||||
needs: [validate-version, create-release]
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build demo
|
||||
run: npm run build:demo
|
||||
|
||||
- name: Deploy demo to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./dist/demo
|
||||
destination_dir: releases/${{ needs.validate-version.outputs.version }}
|
||||
|
||||
- name: Update latest demo link
|
||||
if: needs.validate-version.outputs.is_prerelease == 'false'
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./dist/demo
|
||||
destination_dir: latest
|
||||
Reference in New Issue
Block a user