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@v4 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@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./dist/demo destination_dir: latest