docs(readme): add registry badges, Install section, and nav link #1
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Tag-driven release. Push a tag `vX.Y.Z` (or a prerelease `vX.Y.Z-beta.N`) whose | |
| # base version matches `[workspace.package] version` in Cargo.toml. One synced | |
| # version drives crates.io (code2graph), PyPI (code2graph-rs) and npm (code2graph-rs). | |
| on: | |
| push: | |
| tags: ["v*"] | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| validate-version: | |
| name: Validate version tag | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| is_prerelease: ${{ steps.version.outputs.is_prerelease }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Validate tag against workspace version | |
| id: version | |
| run: | | |
| TAG="${GITHUB_REF_NAME}" | |
| TAG_VERSION="${TAG#v}" | |
| CARGO_VERSION=$(cargo metadata --no-deps --format-version=1 \ | |
| | jq -r '.packages[] | select(.name == "code2graph") | .version') | |
| if [[ ! "$TAG_VERSION" =~ ^([0-9]+\.[0-9]+\.[0-9]+)(-[a-zA-Z]+\.[0-9]+)?$ ]]; then | |
| echo "::error::Invalid tag '$TAG'. Expected vX.Y.Z or vX.Y.Z-label.N" | |
| exit 1 | |
| fi | |
| TAG_BASE="${BASH_REMATCH[1]}" | |
| CARGO_BASE=$(echo "$CARGO_VERSION" | grep -oP '^\d+\.\d+\.\d+') | |
| if [[ "$TAG_BASE" != "$CARGO_BASE" ]]; then | |
| echo "::error::Tag base '$TAG_BASE' != Cargo.toml version '$CARGO_BASE'" | |
| exit 1 | |
| fi | |
| if [[ "$TAG_VERSION" == *-* ]]; then | |
| echo "is_prerelease=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "is_prerelease=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT" | |
| echo "Releasing $TAG_VERSION" | |
| ci: | |
| name: Test | |
| needs: validate-version | |
| uses: ./.github/workflows/test.yml | |
| publish-crates: | |
| name: Publish to crates.io | |
| needs: [validate-version, ci] | |
| runs-on: ubuntu-latest | |
| environment: crates.io | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Stamp version | |
| run: | | |
| VERSION="${{ needs.validate-version.outputs.version }}" | |
| sed -i "0,/^version = \".*\"/s//version = \"$VERSION\"/" Cargo.toml | |
| - name: Publish code2graph | |
| env: | |
| CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} | |
| run: | | |
| VERSION="${{ needs.validate-version.outputs.version }}" | |
| if curl -sf -H "User-Agent: code2graph-ci (github.com/nodedb-lab/code2graph)" \ | |
| "https://crates.io/api/v1/crates/code2graph/$VERSION" > /dev/null 2>&1; then | |
| echo "code2graph@$VERSION already published — skipping" | |
| else | |
| cargo publish -p code2graph --allow-dirty --no-verify | |
| fi | |
| build-sdist: | |
| name: Build sdist | |
| needs: validate-version | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Stamp version | |
| run: | | |
| VERSION="${{ needs.validate-version.outputs.version }}" | |
| PYPI_VERSION=$(echo "$VERSION" | sed -E 's/-alpha\./a/; s/-beta\./b/; s/-rc\./rc/') | |
| sed -i "0,/^version = \".*\"/s//version = \"$VERSION\"/" Cargo.toml | |
| sed -i "s/^version = .*/version = \"$PYPI_VERSION\"/" bindings/python/pyproject.toml | |
| - name: Build sdist | |
| uses: PyO3/maturin-action@v1 | |
| with: | |
| command: sdist | |
| args: --out dist -m bindings/python/Cargo.toml | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: wheels-sdist | |
| path: dist | |
| build-wheels: | |
| name: Build wheel (${{ matrix.target }}) | |
| needs: validate-version | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| target: x86_64-unknown-linux-gnu | |
| manylinux: auto | |
| - os: ubuntu-latest | |
| target: aarch64-unknown-linux-gnu | |
| manylinux: auto | |
| - os: ubuntu-latest | |
| target: x86_64-unknown-linux-musl | |
| manylinux: musllinux_1_2 | |
| - os: macos-13 | |
| target: x86_64-apple-darwin | |
| - os: macos-latest | |
| target: aarch64-apple-darwin | |
| - os: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Stamp version | |
| shell: bash | |
| run: | | |
| VERSION="${{ needs.validate-version.outputs.version }}" | |
| PYPI_VERSION=$(echo "$VERSION" | sed -E 's/-alpha\./a/; s/-beta\./b/; s/-rc\./rc/') | |
| sed -i.bak "0,/^version = \".*\"/s//version = \"$VERSION\"/" Cargo.toml && rm -f Cargo.toml.bak | |
| sed -i.bak "s/^version = .*/version = \"$PYPI_VERSION\"/" bindings/python/pyproject.toml && rm -f bindings/python/pyproject.toml.bak | |
| - name: Build wheel | |
| uses: PyO3/maturin-action@v1 | |
| with: | |
| target: ${{ matrix.target }} | |
| manylinux: ${{ matrix.manylinux || 'auto' }} | |
| args: --release --out dist -m bindings/python/Cargo.toml | |
| sccache: "true" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: wheels-${{ matrix.target }} | |
| path: dist | |
| publish-pypi: | |
| name: Publish to PyPI | |
| needs: [validate-version, build-wheels, build-sdist] | |
| runs-on: ubuntu-latest | |
| environment: pypi | |
| permissions: | |
| id-token: write | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: wheels-* | |
| path: dist | |
| merge-multiple: true | |
| - name: Publish (Trusted Publishing / OIDC) | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| skip-existing: true | |
| build-node: | |
| name: Build addon (${{ matrix.target }}) | |
| needs: validate-version | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - target: x86_64-unknown-linux-gnu | |
| runner: ubuntu-latest | |
| - target: aarch64-unknown-linux-gnu | |
| runner: ubuntu-latest | |
| napi_cross: true | |
| - target: x86_64-unknown-linux-musl | |
| runner: ubuntu-latest | |
| zig: true | |
| - target: x86_64-apple-darwin | |
| runner: macos-13 | |
| - target: aarch64-apple-darwin | |
| runner: macos-latest | |
| - target: x86_64-pc-windows-msvc | |
| runner: windows-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v5 | |
| with: | |
| node-version: "22" | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - uses: Swatinem/rust-cache@v2 | |
| with: | |
| prefix-key: node-${{ matrix.target }} | |
| - name: Install zig (musl cross-compile) | |
| if: matrix.zig | |
| run: | | |
| pip install ziglang | |
| cargo install --locked cargo-zigbuild | |
| - name: Install napi cross-toolchain (linux aarch64) | |
| if: matrix.napi_cross | |
| run: npm install -g @napi-rs/cross-toolchain | |
| - name: Install deps | |
| working-directory: bindings/node | |
| run: npm ci | |
| - name: Build addon | |
| working-directory: bindings/node | |
| run: npx napi build --platform --release --target ${{ matrix.target }} ${{ matrix.zig && '-x' || '' }} ${{ matrix.napi_cross && '--use-napi-cross' || '' }} | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: node-${{ matrix.target }} | |
| path: bindings/node/*.node | |
| publish-npm: | |
| name: Publish to npm | |
| needs: [validate-version, build-node, publish-crates] | |
| runs-on: ubuntu-latest | |
| environment: npm | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v5 | |
| with: | |
| node-version: "22" | |
| registry-url: "https://registry.npmjs.org" | |
| - name: Install deps | |
| working-directory: bindings/node | |
| run: npm ci | |
| - name: Download addon artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: bindings/node/artifacts | |
| pattern: node-* | |
| merge-multiple: true | |
| - name: Stamp version | |
| working-directory: bindings/node | |
| run: | | |
| VERSION="${{ needs.validate-version.outputs.version }}" | |
| jq --arg v "$VERSION" '.version = $v' package.json > tmp.json && mv tmp.json package.json | |
| - name: Assemble platform packages | |
| working-directory: bindings/node | |
| run: | | |
| npx napi create-npm-dirs --npm-dir ./npm | |
| npx napi artifacts --output-dir ./artifacts --npm-dir ./npm | |
| npx napi prepublish -t npm --npm-dir ./npm --skip-optional-publish | |
| - name: Publish (idempotent, with provenance) | |
| working-directory: bindings/node | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| NPM_CONFIG_PROVENANCE: "true" | |
| run: | | |
| publish_pkg() { | |
| local dir="$1" name ver | |
| name=$(jq -r .name "$dir/package.json") | |
| ver=$(jq -r .version "$dir/package.json") | |
| if npm view "$name@$ver" version >/dev/null 2>&1; then | |
| echo "$name@$ver already published — skipping" | |
| else | |
| npm publish "$dir" --access public | |
| fi | |
| } | |
| for dir in npm/*/; do publish_pkg "$dir"; done | |
| publish_pkg . | |
| github-release: | |
| name: GitHub release | |
| needs: [validate-version, publish-crates, publish-pypi, publish-npm] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: softprops/action-gh-release@v2 | |
| with: | |
| generate_release_notes: true | |
| prerelease: ${{ needs.validate-version.outputs.is_prerelease == 'true' }} |