name: Release All Packages on: push: tags: - 'v*' workflow_dispatch: inputs: tag: description: 'Release tag (e.g., v1.1.0)' required: true type: string npm_only: description: 'Release npm package only' required: false type: boolean default: false pypi_only: description: 'Release PyPI package only' required: false type: boolean default: false go_only: description: 'Release Go package only' required: false type: boolean default: false rust_only: description: 'Release Rust crate only' required: false type: boolean default: false test_pypi_only: description: 'Publish to Test PyPI only' required: false type: boolean default: false dry_run: description: 'Dry run (skip actual publish)' required: false type: boolean default: false permissions: contents: write packages: write jobs: validate: runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' - name: Setup Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Setup Go uses: actions/setup-go@v4 with: go-version: '1.21' - name: Setup Rust uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal override: true - name: Check version consistency id: version run: | cd javascript JS_VERSION=$(node -p "require('./package.json').version") cd ../python PY_VERSION=$(grep '^version = ' pyproject.toml | cut -d'"' -f2) cd ../go GO_VERSION=$(grep '^var Version' internal/version/version.go | cut -d'"' -f2) cd ../rust RUST_VERSION=$(grep '^version = ' Cargo.toml | cut -d'"' -f2) if [ "$JS_VERSION" != "$PY_VERSION" ] || [ "$JS_VERSION" != "$GO_VERSION" ] || [ "$JS_VERSION" != "$RUST_VERSION" ]; then echo "Version mismatch: JS=$JS_VERSION, Python=$PY_VERSION, Go=$GO_VERSION, Rust=$RUST_VERSION" exit 1 fi echo "version=$JS_VERSION" >> $GITHUB_OUTPUT echo "Version consistency check passed: $JS_VERSION" - name: Run build script validation run: | python scripts/build_packages.py clean python scripts/build_packages.py test - name: Run Go tests run: | cd go go test -v -race ./... - name: Run Rust tests run: | cd rust cargo test --verbose cargo clippy --all-targets --all-features -- -D warnings release-npm: needs: validate runs-on: ubuntu-latest if: ${{ !github.event.inputs.pypi_only && !github.event.inputs.go_only && !github.event.inputs.rust_only }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' registry-url: 'https://registry.npmjs.org' - name: Install dependencies and test run: | cd javascript npm ci npm test npm run lint - name: Build and test package run: | cd javascript npm pack # Test installation PACKAGE_FILE=$(ls *.tgz) mkdir -p ../test-install cd ../test-install cat > package.json << 'EOF' { "name": "test-install", "version": "1.0.0", "type": "module" } EOF npm install "../javascript/$PACKAGE_FILE" cat > test.js << 'EOF' import { KeyManager, SchemaPinCore } from 'schemapin'; try { const { privateKey, publicKey } = KeyManager.generateKeypair(); const core = new SchemaPinCore(); console.log('✅ Package installation test passed'); } catch (error) { console.error('❌ Package test failed:', error); process.exit(1); } EOF node test.js - name: Publish to npm if: ${{ github.event.inputs.dry_run != 'true' }} continue-on-error: true run: | cd javascript npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} release-pypi: needs: validate runs-on: ubuntu-latest if: ${{ !github.event.inputs.npm_only && !github.event.inputs.go_only && !github.event.inputs.rust_only }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v4 with: python-version: '3.11' - name: Install dependencies and test run: | python -m pip install --upgrade pip pip install build twine cd python pip install -e ".[dev]" python -m pytest tests/ -v ruff check . bandit -r . --exclude tests/ - name: Build and test package run: | cd python python -m build twine check dist/* # Test installation python -m venv test_env source test_env/bin/activate pip install dist/*.whl python -c " import schemapin from schemapin.crypto import KeyManager print('✅ Package installation test passed') " - name: Publish to Test PyPI if: ${{ github.event.inputs.dry_run != 'true' }} continue-on-error: true run: | cd python twine upload --repository testpypi dist/* env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }} - name: Publish to PyPI if: ${{ github.event.inputs.dry_run != 'true' && github.event.inputs.test_pypi_only != 'true' }} run: | cd python twine upload dist/* env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} release-go: needs: validate runs-on: ubuntu-latest if: ${{ !github.event.inputs.npm_only && !github.event.inputs.pypi_only && !github.event.inputs.rust_only }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Go uses: actions/setup-go@v4 with: go-version: '1.21' - name: Install dependencies and test run: | cd go go mod download go mod verify go test -v -race ./... - name: Run linting run: | cd go go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest golangci-lint run - name: Build and test CLI tools run: | cd go make build ./bin/schemapin-keygen --help ./bin/schemapin-sign --help ./bin/schemapin-verify --help - name: Cross-compile binaries if: ${{ github.event.inputs.dry_run != 'true' }} run: | cd go mkdir -p dist # Build for multiple platforms GOOS=linux GOARCH=amd64 go build -o dist/schemapin-keygen-linux-amd64 ./cmd/schemapin-keygen GOOS=linux GOARCH=arm64 go build -o dist/schemapin-keygen-linux-arm64 ./cmd/schemapin-keygen GOOS=darwin GOARCH=amd64 go build -o dist/schemapin-keygen-darwin-amd64 ./cmd/schemapin-keygen GOOS=darwin GOARCH=arm64 go build -o dist/schemapin-keygen-darwin-arm64 ./cmd/schemapin-keygen GOOS=windows GOARCH=amd64 go build -o dist/schemapin-keygen-windows-amd64.exe ./cmd/schemapin-keygen GOOS=linux GOARCH=amd64 go build -o dist/schemapin-sign-linux-amd64 ./cmd/schemapin-sign GOOS=linux GOARCH=arm64 go build -o dist/schemapin-sign-linux-arm64 ./cmd/schemapin-sign GOOS=darwin GOARCH=amd64 go build -o dist/schemapin-sign-darwin-amd64 ./cmd/schemapin-sign GOOS=darwin GOARCH=arm64 go build -o dist/schemapin-sign-darwin-arm64 ./cmd/schemapin-sign GOOS=windows GOARCH=amd64 go build -o dist/schemapin-sign-windows-amd64.exe ./cmd/schemapin-sign GOOS=linux GOARCH=amd64 go build -o dist/schemapin-verify-linux-amd64 ./cmd/schemapin-verify GOOS=linux GOARCH=arm64 go build -o dist/schemapin-verify-linux-arm64 ./cmd/schemapin-verify GOOS=darwin GOARCH=amd64 go build -o dist/schemapin-verify-darwin-amd64 ./cmd/schemapin-verify GOOS=darwin GOARCH=arm64 go build -o dist/schemapin-verify-darwin-arm64 ./cmd/schemapin-verify GOOS=windows GOARCH=amd64 go build -o dist/schemapin-verify-windows-amd64.exe ./cmd/schemapin-verify - name: Create release archives if: ${{ github.event.inputs.dry_run != 'true' }} run: | cd go/dist tar -czf schemapin-go-linux-amd64.tar.gz schemapin-*-linux-amd64 tar -czf schemapin-go-linux-arm64.tar.gz schemapin-*-linux-arm64 tar -czf schemapin-go-darwin-amd64.tar.gz schemapin-*-darwin-amd64 tar -czf schemapin-go-darwin-arm64.tar.gz schemapin-*-darwin-arm64 zip schemapin-go-windows-amd64.zip schemapin-*-windows-amd64.exe sha256sum *.tar.gz *.zip > checksums.txt release-rust: needs: validate runs-on: ubuntu-latest if: ${{ !github.event.inputs.npm_only && !github.event.inputs.pypi_only && !github.event.inputs.go_only }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Rust uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal override: true components: rustfmt, clippy - name: Cache Rust dependencies uses: actions/cache@v3 with: path: | ~/.cargo/registry ~/.cargo/git rust/target key: ${{ runner.os }}-cargo-${{ hashFiles('rust/Cargo.lock') }} - name: Install dependencies and test run: | cd rust cargo fetch cargo test --verbose cargo clippy --all-targets --all-features -- -D warnings cargo fmt --all -- --check - name: Build and test package run: | cd rust cargo build --release cargo package --verbose - name: Publish to crates.io if: ${{ github.event.inputs.dry_run != 'true' }} continue-on-error: true run: | cd rust cargo publish --verbose env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} create-release: needs: [validate, release-npm, release-pypi, release-go, release-rust] runs-on: ubuntu-latest if: ${{ always() && !github.event.inputs.dry_run && startsWith(github.ref, 'refs/tags/') }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Create GitHub Release run: | PRERELEASE="" if [[ "${{ github.ref_name }}" == *"alpha"* ]] || [[ "${{ github.ref_name }}" == *"beta"* ]] || [[ "${{ github.ref_name }}" == *"rc"* ]]; then PRERELEASE="--prerelease" fi # Upload Go binaries if they exist GO_ASSETS="" if [ -d "go/dist" ] && [ "$(ls -A go/dist/*.tar.gz go/dist/*.zip go/dist/checksums.txt 2>/dev/null)" ]; then GO_ASSETS="go/dist/*.tar.gz go/dist/*.zip go/dist/checksums.txt" fi gh release create ${{ github.ref_name }} \ --title "Release ${{ github.ref_name }}" \ --notes "## SchemaPin Release ${{ github.ref_name }} Multi-language cryptographic schema integrity verification package. ### npm Installation \`\`\`bash npm install schemapin \`\`\` ### PyPI Installation \`\`\`bash pip install schemapin \`\`\` ### Go Installation \`\`\`bash go install github.com/ThirdKeyAi/schemapin/go/cmd/...@${{ github.ref_name }} \`\`\` ### Rust Installation \`\`\`toml [dependencies] schemapin = \"${{ github.ref_name }}\" \`\`\` ### CLI Tools \`\`\`bash # Python schemapin-keygen --help schemapin-sign --help schemapin-verify --help # Go (same interface) schemapin-keygen --help schemapin-sign --help schemapin-verify --help \`\`\` ### Rust Usage \`\`\`rust use schemapin::crypto::{generate_key_pair, sign_data, verify_signature}; let key_pair = generate_key_pair()?; let signature = sign_data(&key_pair.private_key_pem, data)?; let is_valid = verify_signature(&key_pair.public_key_pem, data, &signature)?; \`\`\` ### Changes See [CHANGELOG.md](./CHANGELOG.md) for detailed changes. ### Package Links - [npm package](https://www.npmjs.com/package/schemapin) - [PyPI package](https://pypi.org/project/schemapin/) - [Go module](https://pkg.go.dev/github.com/ThirdKeyAi/schemapin/go) - [Rust crate](https://crates.io/crates/schemapin)" \ $GO_ASSETS \ $PRERELEASE env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Required secrets to configure in GitHub repository settings: # - NPM_TOKEN: npm authentication token # - PYPI_API_TOKEN: PyPI API token # - TEST_PYPI_API_TOKEN: Test PyPI API token