name: Release Management on: push: tags: - 'v*' workflow_dispatch: inputs: version: description: 'Version to release' required: true type: string prerelease: description: 'Is this a prerelease?' required: false type: boolean default: false jobs: prepare-release: name: Prepare Release runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} is_prerelease: ${{ steps.version.outputs.is_prerelease }} steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Determine 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/v}" if [[ "$VERSION" == *"-alpha"* ]] || [[ "$VERSION" == *"-beta"* ]] || [[ "$VERSION" == *"-rc"* ]]; then IS_PRERELEASE="true" else IS_PRERELEASE="false" fi fi echo "version=$VERSION" >> $GITHUB_OUTPUT echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT - name: Validate version format run: | VERSION="${{ steps.version.outputs.version }}" if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([-a-zA-Z0-9.]+)?$ ]]; then echo "Invalid version format: $VERSION" exit 1 fi build-artifacts: name: Build Release Artifacts runs-on: ubuntu-latest needs: prepare-release strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install build wheel twine pip install -r requirements.txt pip install -r requirements-dev.txt - name: Build Python package run: | python -m build - name: Run tests run: | chmod +x scripts/run_tests.sh ./scripts/run_tests.sh --verbose unit integration regression - name: Generate documentation run: | chmod +x scripts/generate_api_docs.py python scripts/generate_api_docs.py --output-dir docs/api - name: Create distribution archives run: | # 创建源码分发 python setup.py sdist --formats=gztar,zip # 创建平台特定的二进制分发 if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then python setup.py bdist_wheel --plat-name manylinux1_x86_64 elif [ "${{ matrix.os }}" = "windows-latest" ]; then python setup.py bdist_wheel --plat-name win_amd64 elif [ "${{ matrix.os }}" = "macos-latest" ]; then python setup.py bdist_wheel --plat-name macosx_10_9_x86_64 fi - name: Upload build artifacts uses: actions/upload-artifact@v3 with: name: dist-${{ matrix.os }} path: | dist/ docs/api/ test_reports/ create-release: name: Create GitHub Release runs-on: ubuntu-latest needs: [prepare-release, build-artifacts] permissions: contents: write steps: - name: Download all artifacts uses: actions/download-artifact@v3 - name: Generate release notes run: | VERSION="${{ needs.prepare-release.outputs.version }}" cat > release_notes.md << EOF # CodeDetect $VERSION This release includes bug fixes, performance improvements, and new features. ## What's Changed ### 🚀 Features - Enhanced verification accuracy - Improved performance and scalability - Better FreeRTOS integration - Updated documentation and examples ### 🐛 Bug Fixes - Fixed memory leaks in long-running verification - Improved error handling and reporting - Fixed concurrent access issues ### 📚 Documentation - Updated user manual - Enhanced API documentation - Added more examples and tutorials ## Installation ### From PyPI \`\`\`bash pip install codedetect==$VERSION \`\`\` ### From Source \`\`\`bash git clone https://github.com/codedetect/codedetect.git cd codedetect pip install . \`\`\` ## Requirements - Python 3.8+ - CBMC 5.12+ - FreeRTOS (optional, for embedded verification) ## Support - 📧 Email: support@codedetect.com - 🐛 Issues: [GitHub Issues](https://github.com/codedetect/codedetect/issues) - 📖 Docs: [Online Documentation](https://docs.codedetect.com) --- **Full Changelog**: https://github.com/codedetect/codedetect/compare/$(git describe --tags --abbrev=0)...$VERSION EOF - name: Create Release uses: softprops/action-gh-release@v1 with: tag_name: v${{ needs.prepare-release.outputs.version }} name: CodeDetect ${{ needs.prepare-release.outputs.version }} body_path: release_notes.md draft: false prerelease: ${{ needs.prepare-release.outputs.is_prerelease }} files: | dist-*/dist/* docs/api/** test_reports/** publish-to-pypi: name: Publish to PyPI runs-on: ubuntu-latest needs: [prepare-release, create-release] environment: name: PyPI url: https://pypi.org/p/codedetect steps: - name: Download distribution artifacts uses: actions/download-artifact@v3 with: name: dist-ubuntu-latest path: dist/ - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} packages_dir: dist/ publish-to-docker: name: Publish to Docker Hub runs-on: ubuntu-latest needs: [prepare-release, create-release] steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push Docker image uses: docker/build-push-action@v4 with: context: . push: true tags: | codedetect/codedetect:latest codedetect/codedetect:${{ needs.prepare-release.outputs.version }} platforms: linux/amd64,linux/arm64 build-args: | VERSION=${{ needs.prepare-release.outputs.version }} update-documentation: name: Update Documentation runs-on: ubuntu-latest needs: [prepare-release, create-release] steps: - name: Checkout documentation repo uses: actions/checkout@v4 with: repository: codedetect/docs.codedetect.com token: ${{ secrets.DOCS_DEPLOY_TOKEN }} - name: Download documentation uses: actions/download-artifact@v3 with: name: dist-ubuntu-latest path: docs/ - name: Update documentation run: | # Copy new documentation cp -r docs/api/* . || true # Update version information sed -i "s/latest/${{ needs.prepare-release.outputs.version }}/g" mkdocs.yml || true # Commit changes git config --local user.email "action@github.com" git config --local user.name "GitHub Action" git add . if git diff --staged --quiet; then echo "No changes to commit" else git commit -m "Update documentation for release ${{ needs.prepare-release.outputs.version }}" git push fi notify-users: name: Notify Users runs-on: ubuntu-latest needs: [create-release, publish-to-pypi, publish-to-docker] if: ${{ !needs.prepare-release.outputs.is_prerelease }} steps: - name: Send release notification uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} channel: '#releases' webhook_url: ${{ secrets.SLACK_WEBHOOK }} env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} post-release-tasks: name: Post Release Tasks runs-on: ubuntu-latest needs: [create-release, publish-to-pypi, publish-to-docker] steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - name: Prepare next development version run: | VERSION="${{ needs.prepare-release.outputs.version }}" # Extract version components MAJOR=$(echo $VERSION | cut -d. -f1) MINOR=$(echo $VERSION | cut -d. -f2) PATCH=$(echo $VERSION | cut -d. -f3 | cut -d- -f1) # Increment patch version for next development NEXT_PATCH=$((PATCH + 1)) NEXT_VERSION="${MAJOR}.${MINOR}.${NEXT_PATCH}-dev" # Update version in setup.py and other files sed -i "s/version=\"$VERSION\"/version=\"$NEXT_VERSION\"/g" setup.py || true sed -i "s/__version__ = \"$VERSION\"/__version__ = \"$NEXT_VERSION\"/g" src/__init__.py || true # Create development branch git checkout -b develop git add setup.py src/__init__.py git commit -m "Bump version to $NEXT_VERSION for development" git push origin develop - name: Create milestone for next release uses: actions/github-script@v6 with: script: | const version = "${{ needs.prepare-release.outputs.version }}" const [major, minor] = version.split('.').slice(0, 2).map(Number) const nextMinor = minor + 1 const nextVersion = `${major}.${nextMinor}.0` await github.rest.issues.createMilestone({ owner: context.repo.owner, repo: context.repo.repo, title: nextVersion, description: `Features and improvements for ${nextVersion} release` })