name: Release
on:
push:
tags:
- "v*"
permissions:
contents: write
packages: write
env:
CARGO_TERM_COLOR: always
jobs:
create-release:
name: Create Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Get version from tag
id: get_version
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Extract changelog
id: changelog
run: |
# Extract the version section from CHANGELOG.md
VERSION="${GITHUB_REF#refs/tags/v}"
sed -n "/## \[$VERSION\]/,/## \[/p" CHANGELOG.md | sed '1d;$d' > release_notes.md
cat release_notes.md
- name: Create Release
uses: softprops/action-gh-release@v2
with:
body_path: release_notes.md
draft: false
prerelease: false
generate_release_notes: false
build-release:
name: Build Release Binary
needs: create-release
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
artifact_name: mkdlint
lsp_artifact_name: mkdlint-lsp
asset_name: mkdlint-linux-x86_64
- os: ubuntu-latest
target: aarch64-unknown-linux-gnu
artifact_name: mkdlint
lsp_artifact_name: mkdlint-lsp
asset_name: mkdlint-linux-aarch64
- os: macos-latest
target: x86_64-apple-darwin
artifact_name: mkdlint
lsp_artifact_name: mkdlint-lsp
asset_name: mkdlint-macos-x86_64
- os: macos-latest
target: aarch64-apple-darwin
artifact_name: mkdlint
lsp_artifact_name: mkdlint-lsp
asset_name: mkdlint-macos-aarch64
- os: windows-latest
target: x86_64-pc-windows-msvc
artifact_name: mkdlint.exe
lsp_artifact_name: mkdlint-lsp.exe
asset_name: mkdlint-windows-x86_64.exe
steps:
- uses: actions/checkout@v6
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cross-compilation tools (Linux ARM64)
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu
- name: Configure ARM64 linker
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
mkdir -p .cargo
echo '[target.aarch64-unknown-linux-gnu]' >> .cargo/config.toml
echo 'linker = "aarch64-linux-gnu-gcc"' >> .cargo/config.toml
- name: Build release binaries (CLI + LSP)
run: cargo build --release --target ${{ matrix.target }} --features lsp
- name: Strip binaries (Linux x86_64)
if: matrix.target == 'x86_64-unknown-linux-gnu'
run: |
strip target/${{ matrix.target }}/release/${{ matrix.artifact_name }}
strip target/${{ matrix.target }}/release/${{ matrix.lsp_artifact_name }}
- name: Strip binaries (Linux ARM64)
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
aarch64-linux-gnu-strip target/${{ matrix.target }}/release/${{ matrix.artifact_name }}
aarch64-linux-gnu-strip target/${{ matrix.target }}/release/${{ matrix.lsp_artifact_name }}
- name: Strip binaries (macOS)
if: startsWith(matrix.os, 'macos')
run: |
strip target/${{ matrix.target }}/release/${{ matrix.artifact_name }}
strip target/${{ matrix.target }}/release/${{ matrix.lsp_artifact_name }}
- name: Create archive
shell: bash
run: |
cd target/${{ matrix.target }}/release
if [ "${{ matrix.os }}" = "windows-latest" ]; then
7z a ../../../${{ matrix.asset_name }}.zip ${{ matrix.artifact_name }} ${{ matrix.lsp_artifact_name }}
else
tar czf ../../../${{ matrix.asset_name }}.tar.gz ${{ matrix.artifact_name }} ${{ matrix.lsp_artifact_name }}
fi
- name: Generate SHA256 checksums
shell: bash
run: |
if [ "${{ matrix.os }}" = "windows-latest" ]; then
ARCHIVE="${{ matrix.asset_name }}.zip"
else
ARCHIVE="${{ matrix.asset_name }}.tar.gz"
fi
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256"
elif command -v shasum >/dev/null 2>&1; then
shasum -a 256 "$ARCHIVE" > "${ARCHIVE}.sha256"
else
echo "::error::No SHA256 utility found"
exit 1
fi
echo "Generated checksum:"
cat "${ARCHIVE}.sha256"
- name: Upload Release Asset
uses: softprops/action-gh-release@v2
with:
files: |
./${{ matrix.asset_name }}${{ matrix.os == 'windows-latest' && '.zip' || '.tar.gz' }}
./${{ matrix.asset_name }}${{ matrix.os == 'windows-latest' && '.zip' || '.tar.gz' }}.sha256
- name: Upload LSP binary artifact
uses: actions/upload-artifact@v4
with:
name: lsp-${{ matrix.target }}
path: target/${{ matrix.target }}/release/${{ matrix.lsp_artifact_name }}
build-vscode-extension:
name: Build VS Code Extension (${{ matrix.vscode_target }})
needs: build-release
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- vscode_target: linux-x64
rust_target: x86_64-unknown-linux-gnu
lsp_binary: mkdlint-lsp
- vscode_target: linux-arm64
rust_target: aarch64-unknown-linux-gnu
lsp_binary: mkdlint-lsp
- vscode_target: darwin-x64
rust_target: x86_64-apple-darwin
lsp_binary: mkdlint-lsp
- vscode_target: darwin-arm64
rust_target: aarch64-apple-darwin
lsp_binary: mkdlint-lsp
- vscode_target: win32-x64
rust_target: x86_64-pc-windows-msvc
lsp_binary: mkdlint-lsp.exe
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
working-directory: editors/vscode
run: npm ci
- name: Compile TypeScript
working-directory: editors/vscode
run: npm run compile
- name: Download LSP binary
uses: actions/download-artifact@v4
with:
name: lsp-${{ matrix.rust_target }}
path: editors/vscode/server/
- name: Make binary executable
if: matrix.vscode_target != 'win32-x64'
run: chmod +x editors/vscode/server/${{ matrix.lsp_binary }}
- name: Package VSIX
working-directory: editors/vscode
run: npx vsce package --target ${{ matrix.vscode_target }}
- name: Upload VSIX to release
uses: softprops/action-gh-release@v2
with:
files: editors/vscode/*.vsix
- name: Upload VSIX artifact
uses: actions/upload-artifact@v4
with:
name: vsix-${{ matrix.vscode_target }}
path: editors/vscode/*.vsix
build-vscode-extension-universal:
name: Build VS Code Extension (universal)
needs: create-release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
working-directory: editors/vscode
run: npm ci
- name: Compile TypeScript
working-directory: editors/vscode
run: npm run compile
- name: Package universal VSIX
working-directory: editors/vscode
run: npx vsce package
- name: Upload VSIX to release
uses: softprops/action-gh-release@v2
with:
files: editors/vscode/*.vsix
- name: Upload VSIX artifact
uses: actions/upload-artifact@v4
with:
name: vsix-universal
path: editors/vscode/*.vsix
publish-vscode-extension:
name: Publish to VS Code Marketplace
needs: [build-vscode-extension, build-vscode-extension-universal]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
working-directory: editors/vscode
run: npm ci
- name: Download all VSIX artifacts
uses: actions/download-artifact@v4
with:
pattern: vsix-*
path: editors/vscode/vsix/
merge-multiple: true
- name: Publish to Marketplace
working-directory: editors/vscode
run: npx vsce publish --packagePath vsix/*.vsix
env:
VSCE_PAT: ${{ secrets.VSCE_PAT }}
publish-crate:
name: Publish to crates.io
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Verify version matches tag
run: |
CARGO_VERSION=$(grep '^version =' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
TAG_VERSION=${GITHUB_REF#refs/tags/v}
if [ "$CARGO_VERSION" != "$TAG_VERSION" ]; then
echo "Version mismatch: Cargo.toml has $CARGO_VERSION but tag is $TAG_VERSION"
exit 1
fi
echo "Version check passed: $CARGO_VERSION"
- name: Run tests
run: cargo test --verbose
- name: Run clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Check documentation
run: cargo doc --no-deps
- name: Publish to crates.io
run: cargo publish --token ${{ secrets.CRATES_IO }}
publish-docker:
name: Publish Docker Image
needs: create-release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from tag
id: version
run: echo "version=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT"
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: |
ghcr.io/192d-wing/mkdlint:latest
ghcr.io/192d-wing/mkdlint:${{ steps.version.outputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max