diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..5988965 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,85 @@ +name: Create GitHub Release + +on: + push: + tags: + - "v*" + +jobs: + validate-and-release: + runs-on: windows-latest + env: + CARGO_TERM_COLOR: always + RUSTFLAGS: -D warnings + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Cache Cargo Registry + uses: actions/cache@v3 + with: + path: ~/.cargo/registry + key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-cargo-registry- + + - name: Cache Cargo Git Index + uses: actions/cache@v3 + with: + path: ~/.cargo/git + key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-cargo-index- + + - name: Install Rust + shell: pwsh + run: rustup update stable && rustup default stable + + - name: Install PSSemVer + shell: pwsh + run: | + try { + Import-Module -Name PSSemVer -ErrorAction Stop + } catch { + Write-Host "Installing PSSemVer module..." + Install-Module -Name PSSemVer -Scope CurrentUser -Force -ErrorAction Stop + Import-Module -Name PSSemVer -ErrorAction Stop + } + + - name: Validate Tag with PSSemVer + id: validate + shell: pwsh + run: | + $tagName = "${{ github.ref_name }}" + try { + $rawVersion = $tagName -replace '^v', '' + $Version = [PSSemVer]::Parse($rawVersion) + if ($Version.Prerelease) { + echo "::set-output name=prerelease::true" + } else { + echo "::set-output name=prerelease::false" + } + } catch { + Write-Error "Tag name does not contain a valid semantic version. Current tag: $tagName" + exit 1 + } + continue-on-error: false + + - name: Cargo Publish Dry-Run + run: cargo publish --dry-run + + - name: Create GitHub Release + id: release + uses: actions/create-release@v1 + with: + tag_name: ${{ github.ref_name }} + release_name: | + ${{ steps.validate.outputs.prerelease == 'true' && 'Prerelease' || 'Release' }} ${{ github.ref_name }} + body: | + This is a ${{ steps.validate.outputs.prerelease == 'true' && 'prerelease' || 'release' }} of the crate. + You can find the [main crate here](https://crates.io/crates/${{ github.repository }}).: + prerelease: ${{ steps.validate.outputs.prerelease }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Cargo Publish + run: cargo publish diff --git a/.github/workflows/release-checks.yml b/.github/workflows/release-checks.yml new file mode 100644 index 0000000..39fa227 --- /dev/null +++ b/.github/workflows/release-checks.yml @@ -0,0 +1,151 @@ +on: + push: + branches: + - release/* + pull_request: + branches: + - release/* + +jobs: + version-check: + runs-on: windows-latest + name: "Check crate versions" + env: + CARGO_TERM_COLOR: always + RUSTFLAGS: -D warnings + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Cache Cargo Dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-dependencies-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-cargo-dependencies- + + - name: Cache PowerShell Modules + uses: actions/cache@v3 + with: + path: | + $env:USERPROFILE\Documents\WindowsPowerShell\Modules + key: ${{ runner.os }}-powershell-modules + restore-keys: ${{ runner.os }}-powershell-modules- + + - name: Install Rust + shell: pwsh + run: rustup update stable && rustup default stable + + - name: Install PSSemVer + shell: pwsh + run: | + try { + Import-Module -Name PSSemVer -ErrorAction Stop + } catch { + Write-Host "Installing PSSemVer module..." + Install-Module -Name PSSemVer -Scope CurrentUser -Force -ErrorAction Stop + Import-Module -Name PSSemVer -ErrorAction Stop + } + + - name: Extract Branch Version + id: extract_version + shell: pwsh + run: | + $branchName = "${{ github.ref_name }}" + try { + $rawVersion = $branchName -replace '^release/', '' + $expectedVersion = [PSSemVer]::Parse($rawVersion) + + + Write-Output "expected_version=$expectedVersion" | Out-File -FilePath $GITHUB_OUTPUT -Encoding utf8 + Write-Host "Expected version for crates: $expectedVersion" + } catch { + Write-Error "Branch name does not contain a valid semantic version. Current branch: $branchName" + exit 1 + } + + - name: Parse and Compare Crate Versions + shell: pwsh + env: + EXPECTED_VERSION: ${{ steps.extract_version.outputs.expected_version }} + run: | + try { + $expectedSemVer = [PSSemVer]::Parse($env:EXPECTED_VERSION) + } catch { + Write-Error "Expected version '$env:EXPECTED_VERSION' is not a valid semantic version." + exit 1 + } + + # Retrieve workspace metadata + $metadataJson = cargo metadata --format-version 1 + $metadata = $metadataJson | ConvertFrom-Json + $workspaceMembers = $metadata.workspace_members + + $errors = @() + + foreach ($package in $metadata.packages) { + # Skip non-workspace members + if (-not ($workspaceMembers -contains $package.id)) { + continue + } + + $name = $package.name + $semVer = [PSSemVer]::Parse($package.version) + + if ($semVer.CompareTo($expectedSemVer) -ne 0) { + if ($package.publish -ne $false) { + $errors += "ERROR: Publishable crate '$name' has version '$semVer', expected '$expectedSemVer'." + } else { + Write-Warning "Non-publishable crate '$name' has version '$semVer', expected '$expectedSemVer'." + } + } else { + Write-Host "Crate '$name' with version '$semVer' matches the branch version." + } + } + + if ($errors.Count -gt 0) { + $errors | ForEach-Object { Write-Error $_ } + exit 1 + } + + publish-dry-run: + needs: version-check + runs-on: windows-latest + name: "Publish Dry-Run" + env: + CARGO_TERM_COLOR: always + RUSTFLAGS: -D warnings + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Cache Cargo Dependencies + uses: actions/cache@v3 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: ${{ runner.os }}-cargo-dependencies-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-cargo-dependencies- + + - name: Install Rust + shell: pwsh + run: rustup update stable && rustup default stable + + - name: Run Tests + shell: pwsh + run: | + echo "Running tests..." + cargo test --all-targets + + - name: Publish Dry-Run + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} + shell: pwsh + run: | + echo "Running cargo publish dry-run..." + cargo publish --dry-run diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml new file mode 100644 index 0000000..ae5612d --- /dev/null +++ b/.github/workflows/release-tag.yml @@ -0,0 +1,44 @@ +name: Tag on Merge to Master + +on: + pull_request: + types: + - closed + branches: + - master + +jobs: + create-tag: + if: ${{ github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') }} + runs-on: windows-latest + env: + CARGO_TERM_COLOR: always + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Extract Version from Branch Name + id: extract_version + shell: pwsh + run: | + $branchName = "${{ github.event.pull_request.head.ref }}" + $version = $branchName -replace '^release/', '' + Write-Host "Extracted version: $version" + echo "version=$version" >> $GITHUB_ENV + + - name: Create Git Tag + id: create_tag + run: | + git config user.name "GitHub Actions" + git config user.email "actions@github.com" + git tag "v${{ env.version }}" -a -m "Release version ${{ env.version }}" + git push origin "v${{ env.version }}" + + - name: Verify Tag + run: | + git fetch --tags + if (! git tag | grep -q "v${{ env.version }}") { + echo "Tag creation failed for version ${{ env.version }}." + exit 1 + } diff --git a/plugin/Cargo.toml b/plugin/Cargo.toml index 0b5505b..0905bcb 100644 --- a/plugin/Cargo.toml +++ b/plugin/Cargo.toml @@ -5,6 +5,7 @@ version.workspace = true license.workspace = true repository.workspace = true edition = "2021" +publish = false [lib] crate-type = ["cdylib"] diff --git a/wslplugins-macro-tests/Cargo.toml b/wslplugins-macro-tests/Cargo.toml index 2430b84..d77e33a 100644 --- a/wslplugins-macro-tests/Cargo.toml +++ b/wslplugins-macro-tests/Cargo.toml @@ -6,6 +6,7 @@ license.workspace = true repository.workspace = true description = "A Rust framework for developing WSL plugins using safe and idiomatic Rust." edition = "2021" +publish = false [dependencies] wslplugins-rs = { path = "../wslplugins-rs", features = ["macro"] }