From 2b2df418accad4172ce3684c3af87857537dcefd Mon Sep 17 00:00:00 2001 From: Sewer56 Date: Sat, 22 Jun 2024 23:49:45 +0100 Subject: [PATCH] Initial Version --- .github/workflows/test-build-workflow.yml | 315 -------------------- .github/workflows/test-publish-workflow.yml | 72 +++++ README.MD | 285 ++++-------------- action.yml | 276 ++++------------- 4 files changed, 199 insertions(+), 749 deletions(-) delete mode 100644 .github/workflows/test-build-workflow.yml create mode 100644 .github/workflows/test-publish-workflow.yml diff --git a/.github/workflows/test-build-workflow.yml b/.github/workflows/test-build-workflow.yml deleted file mode 100644 index 7bce5a0..0000000 --- a/.github/workflows/test-build-workflow.yml +++ /dev/null @@ -1,315 +0,0 @@ -name: Test Build Workflow - -on: - schedule: - - cron: '0 0 * * *' # Run daily at midnight - workflow_dispatch: - push: - branches: [ master ] - tags: - - 'v1' - - 'v1-test' - paths: - - 'action.yml' - - '.github/workflows/test-build-workflow.yml' - pull_request: - branches: [ master ] - paths: - - 'action.yml' - - '.github/workflows/test-build-workflow.yml' - -jobs: - test-binary-build: - strategy: - matrix: - include: - - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - use-pgo: true - use-cross: false - - os: ubuntu-latest - target: i686-unknown-linux-gnu - use-pgo: true - use-cross: false - - os: ubuntu-latest - target: aarch64-unknown-linux-gnu - use-pgo: true # x64 host to aarch64 simulated guest via cross - use-cross: true - - os: ubuntu-latest - target: armv7-unknown-linux-gnueabihf - use-pgo: true # x64 host to armv7 simulated guest via cross - use-cross: true - - os: windows-latest - target: x86_64-pc-windows-msvc - use-pgo: true - use-cross: false - - os: windows-latest - target: i686-pc-windows-msvc - use-pgo: true - use-cross: false - - os: windows-latest - target: aarch64-pc-windows-msvc - use-pgo: false # no virtualization support (proprietary OS) - use-cross: false - - os: macos-13 # x86 - target: x86_64-apple-darwin - use-pgo: true - use-cross: false - - os: macos-14 # M1 - target: aarch64-apple-darwin - use-pgo: true - use-cross: false - runs-on: ${{ matrix.os }} - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: 149060527e685360687d7332742ac016b39af8a7 - - name: Test Binary Build - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - target: ${{ matrix.target }} - use-pgo: ${{ matrix.use-pgo }} - use-cross: ${{ matrix.use-cross }} - rust-project-path: "tools/cli" - crate-name: "prs-rs-cli" - upload-artifacts: false - - test-library-build: - strategy: - matrix: - include: - - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - use-pgo: true - use-cross: false - - os: ubuntu-latest - target: i686-unknown-linux-gnu - use-pgo: true - use-cross: false - - os: ubuntu-latest - target: aarch64-unknown-linux-gnu - use-pgo: true # x64 host to aarch64 simulated guest via cross - use-cross: true - - os: ubuntu-latest - target: armv7-unknown-linux-gnueabihf - use-pgo: true # x64 host to armv7 simulated guest via cross - use-cross: true - - os: windows-latest - target: x86_64-pc-windows-msvc - use-pgo: true - use-cross: false - - os: windows-latest - target: i686-pc-windows-msvc - use-pgo: true - use-cross: false - # No native host to run tests and proprietary compiler. - #- os: windows-latest - # target: aarch64-pc-windows-msvc - # use-pgo: false # no virtualization support (proprietary OS) - # use-cross: false - - os: macos-13 # x86 - target: x86_64-apple-darwin - use-pgo: true - use-cross: false - - os: macos-14 # M1 - target: aarch64-apple-darwin - use-pgo: true - use-cross: false - runs-on: ${{ matrix.os }} - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: 149060527e685360687d7332742ac016b39af8a7 - - name: Test Library Build - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - crate-name: prs-rs - target: ${{ matrix.target }} - use-pgo: ${{ matrix.use-pgo }} - use-cross: ${{ matrix.use-cross }} - features: "c-exports" - build-library: true - upload-artifacts: false - run-tests-and-coverage: true - upload-coverage-to-codecov: false - - # This tests gathering PGO data on a host, and building for a different target. - test-pgo-with-cross-compile: - runs-on: ubuntu-latest - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: 149060527e685360687d7332742ac016b39af8a7 - - name: Test PGO with Cross-Compilation (Binary) - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - rust-project-path: tools/cli - pgo-project-path: . - crate-name: prs-rs-cli - target: aarch64-unknown-linux-gnu # x64 host to aarch64 simulated guest - use-pgo: true - use-cross: true - pgo-benchmark-name: my_benchmark - upload-artifacts: false - - name: Test PGO with Cross-Compilation (Library) - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - crate-name: prs-rs - target: aarch64-unknown-linux-gnu # x64 host to to aarch64 simulated guest - use-pgo: true - use-cross: true - pgo-benchmark-name: my_benchmark - upload-artifacts: false - build-library: true - - test-library-feature-build: - runs-on: ubuntu-latest - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: 149060527e685360687d7332742ac016b39af8a7 - - name: Test Library Feature Build - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - crate-name: prs-rs - target: x86_64-unknown-linux-gnu - features: c-exports,std - upload-artifacts: false - build-library: true - - test-library-no-default-features: - runs-on: ubuntu-latest - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: 149060527e685360687d7332742ac016b39af8a7 - - name: Test Library No Default Features - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - crate-name: prs-rs - target: x86_64-unknown-linux-gnu - no-default-features: true - features: std - upload-artifacts: false - build-library: true - - test-binary-pgo-with-library: - runs-on: ubuntu-latest - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: 149060527e685360687d7332742ac016b39af8a7 - - name: Test Binary PGO with Library - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - rust-project-path: tools/cli - pgo-project-path: . - crate-name: prs-rs-cli - target: x86_64-unknown-linux-gnu - use-pgo: true - pgo-benchmark-name: my_benchmark - upload-artifacts: false - - test-library-pgo: - runs-on: ubuntu-latest - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: 149060527e685360687d7332742ac016b39af8a7 - - name: Test Library PGO - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - crate-name: prs-rs - target: x86_64-unknown-linux-gnu - use-pgo: true - pgo-benchmark-name: my_benchmark - upload-artifacts: false - build-library: true - - test-custom-rustflags: - runs-on: ubuntu-latest - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: 149060527e685360687d7332742ac016b39af8a7 - - name: Test Custom RUSTFLAGS (Binary) - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - rust-project-path: tools/cli - crate-name: prs-rs-cli - target: x86_64-unknown-linux-gnu - additional-rustflags: -C opt-level=3 - upload-artifacts: false - - name: Test Custom RUSTFLAGS (Library) - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - crate-name: prs-rs - target: x86_64-unknown-linux-gnu - additional-rustflags: -C opt-level=3 - upload-artifacts: false - build-library: true - - test-artifact-upload: - runs-on: ubuntu-latest - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: 149060527e685360687d7332742ac016b39af8a7 - - - name: Test Artifact Upload (Binary) - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - rust-project-path: tools/cli - crate-name: prs-rs-cli - target: x86_64-unknown-linux-gnu - - - name: Download Binary Artifact - uses: actions/download-artifact@v4 - with: - name: prs-rs-cli-x86_64-unknown-linux-gnu- - - - name: Assert Binary Artifact - shell: bash - run: | - if [ ! -f prs-rs-cli ]; then - echo "Binary artifact not found" - exit 1 - fi - - - name: Test Artifact Upload (Library) - uses: Reloaded-Project/devops-rust-lightweight-binary@v1-test - with: - crate-name: prs-rs - target: x86_64-unknown-linux-gnu - build-library: true - - - name: Download Library Artifact - uses: actions/download-artifact@v4 - with: - name: C-Library-x86_64-unknown-linux-gnu- - - - name: Assert Library Artifact - shell: bash - run: | - if [ ! -f libprs_rs.a ] || [ ! -f libprs_rs.so ]; then - echo "Library artifacts not found" - exit 1 - fi \ No newline at end of file diff --git a/.github/workflows/test-publish-workflow.yml b/.github/workflows/test-publish-workflow.yml new file mode 100644 index 0000000..daad54c --- /dev/null +++ b/.github/workflows/test-publish-workflow.yml @@ -0,0 +1,72 @@ +name: Test Publish Action + +on: + push: + tags: [ 'v1', 'v1-test' ] + pull_request: + branches: [ main ] + +jobs: + + build_artifacts: + runs-on: ubuntu-latest + steps: + - name: Checkout prs-rs Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: d08599ed5473616f57d57a0966939e1a5dbda9b4 + + - name: Build Rust C Library + uses: Reloaded-Project/devops-rust-lightweight-binary@v1 + with: + crate-name: prs-rs + target: x86_64-unknown-linux-gnu + use-pgo: false + use-cross: false + features: "c-exports" + build-library: true + upload-artifacts: true + + - name: Build .NET Library + uses: Reloaded-Project/devops-rust-c-library-to-dotnet@v1 + with: + csharp-project-path: bindings/csharp + + test_publish_action: + needs: build_artifacts + runs-on: ubuntu-latest + steps: + - name: Checkout prs-rs Repository + uses: actions/checkout@v4 + with: + repository: Sewer56/prs-rs + ref: d08599ed5473616f57d57a0966939e1a5dbda9b4 + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + path: artifacts + + - name: Test Publish Action + uses: Reloaded-Project/devops-publish-action@v1-test + with: + crates-io-token: ${{ secrets.CRATES_IO_TOKEN }} + additional-publish-params: --dry-run + create-release: false + + - name: Verify NuGet packages + run: | + if ls artifacts/**/*.nupkg 1> /dev/null 2>&1; then + echo "NuGet packages found" + else + echo "No NuGet packages found" + exit 1 + fi + + if ls artifacts/**/*.snupkg 1> /dev/null 2>&1; then + echo "NuGet symbol packages found" + else + echo "No NuGet symbol packages found" + exit 1 + fi \ No newline at end of file diff --git a/README.MD b/README.MD index 68b0f70..13fd08a 100644 --- a/README.MD +++ b/README.MD @@ -1,254 +1,93 @@
- - reloaded Logo + + Logo -

Reloaded Rust Build C Library Workflow

+

Reloaded Publish Action

-

- - License - +

+ License

-This is a GitHub Action that can be used to build an optimized, lightweight binary (or C library) -from a Rust project. +This GitHub Action is designed to streamline the publishing process for Reloaded projects by +automatically detecting and uploading artifacts to the appropriate locations, such as GitHub +Releases, NuGet, and crates.io. -This action is used to build binaries with the following properties: +## Features -- **Self-Built std**: Reduces binary size and improves optimizations. -- **Abort on Panic**: Reduces binary size. Can be disabled if needed. -- **Profile Guided Optimization (PGO)**: Improves performance by optimizing based on usage patterns. -- **Cross-Compilation**: Supports cross-compilation using `cross-rs`. -- **Nightly Rust**: Uses the nightly Rust toolchain for building and running. -- **Tests and Coverage**: Optionally run tests and generate coverage reports using the `devops-rust-test-and-coverage` action. +- 📦 Download artifacts generated by other GitHub Actions +- 🚀 Upload artifacts to GitHub Releases +- 📦 Publish NuGet packages to nuget.org +- 🦀 Publish Rust packages to crates.io +- 🔍 Automatically detect and upload the appropriate artifacts -It can be used to build both binaries and C libraries. +## Usage -## Example Usage - -As a single job/step of a workflow: - -```yaml -test-binary-build: - strategy: - matrix: - include: - - os: ubuntu-latest - target: x86_64-unknown-linux-gnu - use-pgo: true - use-cross: false - - os: ubuntu-latest - target: i686-unknown-linux-gnu - use-pgo: true - use-cross: false - - os: ubuntu-latest - target: aarch64-unknown-linux-gnu - use-pgo: false # no native runner - use-cross: true - - os: ubuntu-latest - target: armv7-unknown-linux-gnueabihf - use-pgo: false # no native runner - use-cross: true - - os: windows-latest - target: x86_64-pc-windows-msvc - use-pgo: true - use-cross: false - - os: windows-latest - target: i686-pc-windows-msvc - use-pgo: true - use-cross: false - - os: windows-latest - target: aarch64-pc-windows-msvc - use-pgo: false # no native runner - use-cross: false - - os: macos-13 # x86 - target: x86_64-apple-darwin - use-pgo: true - use-cross: false - - os: macos-14 # M1 - target: aarch64-apple-darwin - use-pgo: true - use-cross: false - runs-on: ${{ matrix.os }} - steps: - - name: Checkout Test Repository - uses: actions/checkout@v4 - with: - repository: Sewer56/prs-rs - ref: d08599ed5473616f57d57a0966939e1a5dbda9b4 - - name: Test Binary Build - uses: Reloaded-Project/devops-rust-lightweight-binary@v1 - with: - target: ${{ matrix.target }} - use-pgo: ${{ matrix.use-pgo }} - use-cross: ${{ matrix.use-cross }} - rust-project-path: "tools/cli/" - crate-name: "prs-rs-cli" - upload-artifacts: false - run-tests-and-coverage: true -``` - -## Setup - -To use this action in your own repository: - -1. Create a new workflow file (e.g., `.github/workflows/build-c-library.yml`) in your repository. -2. Copy the example usage job from above into the new workflow file. -3. Customize the input parameters as needed for your project. - -## Configuration - -### Inputs - -| Input | Required | Default | Description | -| ---------------------------- | -------- | ---------------- | -------------------------------------------------------------------------------------- | -| `rust-project-path` | No | `.` | Path to the Rust project | -| `pgo-project-path` | No | `.` | Path to the Rust project used for gathering PGO data. Can be same or separate project. | -| `crate-name` | Yes | | Name of the Rust crate (used to determine file name) | -| `target` | Yes | | The target platform for the Rust compiler | -| `features` | No | `''` | Comma-separated list of features to include in the build | -| `no-default-features` | No | `false` | Do not include default features in the build | -| `use-pgo` | No | `false` | Use Profile-Guided Optimization [PGO] to build the library. | -| `pgo-benchmark-name` | No | `'my_benchmark'` | Benchmark name to use with PGO. | -| `use-cross` | No | `false` | Use cross-rs for building. If false, use cargo. | -| `additional-rustflags` | No | `''` | Additional RUSTFLAGS to pass to the Rust compiler | -| `upload-artifacts` | No | `true` | Upload the built artifacts as a GitHub Actions artifact | -| `abort-on-panic` | No | `true` | Abort immediately on panic. If false, the default panic handler is used. | -| `build-library` | No | `false` | Build a library instead of a binary. | -| `run-tests-and-coverage` | No | `false` | Run tests and coverage using the `devops-rust-test-and-coverage` action. | -| `upload-coverage-to-codecov` | No | `true` | Uploads coverage to codecov if `run-tests-and-coverage` is enabled. | - -### Setting up Profile-Guided Optimization (PGO) - -Profile-Guided Optimization works by compiling and executing a benchmark whose name and project -can be defined by `pgo-benchmark-name` and `pgo-project-path` respectively. So you should strive -to keep the benchmark as close to the final usage of your application as possible. - -A benchmark for PGO can be defined as follows: - -```rust -// Regular benchmarks, not PGO -#[cfg(not(feature = "pgo"))] -{ - bench_estimate(c); - bench_decompress(c); - bench_compress_file(c); - bench_create_dict(c); -} - -// Benchmark with realistic usage patterns for PGO. -#[cfg(feature = "pgo")] -{ - generate_pgo_data(); -} -``` - -Then said profile is used to build the final version of your application. - -For PGO to work, the `target` platform must be the same as the host that generated the profiling -data. Sometimes you can get away with using `cross` to achieve this, for example: +To use this action in your GitHub workflow, add the following step: ```yaml -# Host is x86-linux but this seems to work just a-ok! -target: aarch64-unknown-linux-gnu # x64 host to to aarch64 simulated guest -use-pgo: true -use-cross: true -``` - -If the process fails, your CI will fail, so do experiment. - -## Running Tests and Coverage - -To run tests and generate coverage reports as part of the build process, set the -`run-tests-and-coverage` input to `true`. - -This will invoke the [devops-rust-test-and-coverage][devops-test-coverage] action after the build -step, using the same configuration as the build (e.g., `target`, `features`, `use-cross`, etc.). - -The `devops-rust-test-and-coverage` action will run tests using either `cargo` or `cross`, -depending on the `use-cross` input. If `use-cross` is `false`, it will also generate a coverage -report using Tarpaulin and upload it to Codecov (if `upload-coverage` is `true`). - -Note that code coverage is skipped when using `cross` due to incompatibility with Tarpaulin. - -## Building Libraries +publish-crate: + permissions: + contents: write -To build a library instead of a binary, set the `build-library` input to `true`. -This is equivalent to setting `crate-type = ["cdylib", "staticlib"]` in `Cargo.toml`. + # Dependencies that produce publish-able artifacts. + needs: [build-and-test,build-c-headers,build-dotnet-library] -When building a library, the generated artifacts will include static libraries (`.a`, `.lib`) -and dynamic libraries (`.so`, `.dll`, `.dylib`) depending on the target platform. - -## Examples - -Find more examples in [the tests](./.github/workflows/test-rust-build-c-library-workflow.yml). - -### Custom PGO Project Path - -```yaml -- name: Build C Library - uses: Reloaded-Project/devops-rust-lightweight-binary@v1 - with: - rust-project-path: ./rust-project - pgo-project-path: ./pgo-project - crate-name: my-crate - target: x86_64-unknown-linux-gnu -``` - -### Using cross-rs for Building - -```yaml -- name: Build C Library - uses: Reloaded-Project/devops-rust-lightweight-binary@v1 - with: - crate-name: my-crate - target: x86_64-unknown-linux-gnu - use-cross: true -``` - -### Custom Additional RUSTFLAGS - -```yaml -- name: Build C Library - uses: Reloaded-Project/devops-rust-lightweight-binary@v1 - with: - crate-name: my-crate - target: x86_64-unknown-linux-gnu - additional-rustflags: -C opt-level=3 + # Publish only on tags + if: startsWith(github.ref, 'refs/tags/') + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Publish artifacts + uses: Reloaded-Project/devops-publish-action@v1 + with: + nuget-api-key: ${{ secrets.NUGET_KEY }} + crates-io-token: ${{ secrets.CRATES_IO_TOKEN }} + rust-project-paths: | + ./path/to/rust/project1 + ./path/to/rust/project2 ``` -## Accessing the Built Artifacts +## Inputs -After a successful run, the built artifacts will be available as a downloadable -artifact in the GitHub Actions run. +| Input | Description | Required | Default | +| --------------------------- | ----------------------------------------------------------- | -------- | ----------- | +| `nuget-api-key` | NuGet API key for publishing packages | No | | +| `crates-io-token` | Crates.io token for publishing Rust packages | No | | +| `rust-project-paths` | List of paths to Rust projects | No | `.` | +| `artifacts-directory` | Path to the directory containing the artifacts | No | `artifacts` | +| `additional-publish-params` | Additional parameters for cargo publish | No | `''` | +| `create-release` | Whether the artifacts should be uploaded to GitHub Releases | No | `true` | -For binary builds, the artifact will be named `${{ inputs.crate-name }}-${{ inputs.target }}-${{ inputs.features }}`. +## How this Action Works -For library builds, the artifact will be named `C-Library-${{ inputs.target }}-${{ inputs.features }}`. +- Downloads all artifacts and re-uploads them to the GitHub Releases. +- Uploads all NuGet packages stored in artifacts to `nuget.org` +- Uploads specified Rust project paths to `crates.io` -To access the artifacts: +## Why this Action Exists -1. Navigate to the Actions tab in your repository. -2. Click on the workflow run that built the artifacts. -3. In the "Artifacts" section, you will find the generated artifacts, which you can download. +Reloaded projects produce various types of artifacts, such as binaries, libraries, NuGet packages, +and Rust packages. This action makes it easy to publish these artifacts. -## Why this Exists? +This action is designed to be used in conjunction with actions such as: -Building C libraries from Rust projects can be a complex process, especially when -considering different target platforms, compiler flags, and optimizations like PGO. +- [devops-changelog](https://github.com/Reloaded-Project/devops-changelog) +- [devops-rust-cbindgen](https://github.com/Reloaded-Project/devops-rust-cbindgen) +- [devops-rust-lightweight-binary](https://github.com/Reloaded-Project/devops-rust-lightweight-binary) -This action simplifies the process by providing a configurable and reusable workflow -that handles the building of C libraries from Rust projects. +This action centralizes the publishing logic, ensuring consistency across projects and reducing +maintenance overhead. ## Contributing -Contributions are welcome! If you encounter any issues or have suggestions for improvements, -please open an issue or submit a pull request in this repository. +Contributions are welcome! -## License +If you encounter any issues or have suggestions for improvements, please +open an issue or submit a pull request in this repository. -This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. +## License -[devops-test-coverage]: https://github.com/Reloaded-Project/devops-rust-test-and-coverage \ No newline at end of file +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. \ No newline at end of file diff --git a/action.yml b/action.yml index cdb2a58..9ca0bc4 100644 --- a/action.yml +++ b/action.yml @@ -1,241 +1,95 @@ -name: 'Build Optimized Rust Binary' -description: 'Builds a min sized Rust binary or library. With self-built std, abort on panic, PGO and cross-compilation support.' +name: 'Reloaded Publish Action' +description: 'Publish artifacts from other GitHub Actions' +author: 'Reloaded Project' branding: - icon: 'check' + icon: 'package' color: 'red' inputs: - rust-project-path: - description: 'Path to the Rust project' + nuget-api-key: + description: 'NuGet API key for publishing packages' required: false - default: '.' - pgo-project-path: - description: 'Path to the Rust project used for gathering PGO data. Can be same or separate project.' - required: false - default: '.' - crate-name: - description: 'Name of the Rust crate (used to determine file name)' - required: true - target: - description: 'The target platform for the Rust compiler' - required: true - features: - description: 'Comma-separated list of features to include in the build' + crates-io-token: + description: 'Crates.io token for publishing Rust packages' required: false - default: '' - no-default-features: - description: 'Do not include default features in the build' + rust-project-paths: + description: 'List of paths to Rust projects' required: false - default: false - use-pgo: - description: 'Use Profile-Guided Optimization [PGO] to build the artifact.' - required: false - default: false - pgo-benchmark-name: - description: 'Benchmark name to use with PGO.' - required: false - default: 'my_benchmark' - use-cross: - description: 'Use cross-rs for building. If false, use cargo.' + default: '.' + artifacts-directory: + description: 'Path to the directory containing the artifacts' required: false - default: false - additional-rustflags: - description: 'Additional RUSTFLAGS to pass to the Rust compiler' + default: 'artifacts' + additional-publish-params: + description: 'Additional parameters for cargo publish (e.g., --dry-run)' required: false default: '' - upload-artifacts: - description: 'Upload the built artifacts as a GitHub Actions artifact' - required: false - default: true - abort-on-panic: - description: 'Abort immediately on panic. If false, the default panic handler is used.' - required: false - default: true - build-library: - description: 'Build a library instead of a binary. Requires `crate-type = ["cdylib", "staticlib"]` in Cargo.toml.' - required: false - default: false - run-tests-and-coverage: - description: 'Run tests and coverage using the `devops-rust-test-and-coverage` action.' - required: false - default: false - upload-coverage-to-codecov: - description: 'Uploads coverage to codecov if `run-tests-and-coverage` is enabled.' - required: false - default: true - codecov-token: - description: 'Codecov token for uploading coverage' + create-release: + description: 'Whether the artifacts should by uploaded to GitHub releases.' required: false + default: 'true' runs: using: 'composite' steps: - - uses: actions-rust-lang/setup-rust-toolchain@v1 + - name: Checkout repository + uses: actions/checkout@v4 with: - matcher: false - cache: false - toolchain: nightly + submodules: recursive - - name: Setup Rust Caching - uses: Swatinem/rust-cache@v2 + - name: Download artifacts + uses: actions/download-artifact@v4 with: - key: ${{ inputs.rust-project-path }}+${{ inputs.target }} - cache-on-failure: true - workspaces: | - ${{ inputs.rust-project-path }} -> target + path: ${{ inputs.artifacts-directory }} - - name: Install gcc-multilib (if on Ubuntu based System, and Target is not Host) - if: inputs.use-cross == 'false' && runner.os == 'Linux' - shell: bash + - name: Upload to NuGet + if: inputs.nuget-api-key != '' + shell: pwsh run: | - # Get host triple - HOST_TARGET=$(rustc -vV | sed -n 's|host: ||p') - echo "Host target: $HOST_TARGET" - echo "Target: ${{ inputs.target }}" + $items = Get-ChildItem -Path "${{ inputs.artifacts-directory }}/**.nupkg" -Recurse + Foreach ($item in $items) + { + Write-Host "Pushing $item" + dotnet nuget push "$item" -k "${{ inputs.nuget-api-key }}" -s "https://api.nuget.org/v3/index.json" --skip-duplicate + } - if [ "$HOST_TARGET" != "${{ inputs.target }}" ]; then - echo "Target is different from host. Installing gcc-multilib..." - sudo apt-get update || true - sudo apt-get install -y gcc-multilib || true - else - echo "Target is the same as host. Skipping gcc-multilib installation." - fi + $items = Get-ChildItem -Path "${{ inputs.artifacts-directory }}/**.snupkg" -Recurse + Foreach ($item in $items) + { + Write-Host "Pushing Symbol Package $item" + dotnet nuget push "$item" -k "${{ inputs.nuget-api-key }}" -s "https://api.nuget.org/v3/index.json" --skip-duplicate + } - - name: Setup Rust Toolchain + - name: Compress artifacts shell: bash - working-directory: ${{ inputs.rust-project-path }} run: | - rustup target add ${{ inputs.target }} - rustup component add rust-src --toolchain nightly - rustup toolchain install nightly-${{ inputs.target }} --force-non-host - - # Install cross-rs if needed - if [ "${{ inputs.use-cross }}" == "true" ]; then - cargo install cross --git https://github.com/cross-rs/cross + dir="${{ inputs.artifacts-directory }}" + if [ ! -d "$dir" ]; then + echo "Directory $dir does not exist. No artifacts found." + exit 0 fi - - name: Build Rust Project - shell: bash - run: | - # Setup build variables - BUILD_CMD="cargo" - if [ "${{ inputs.use-cross }}" == "true" ]; then - BUILD_CMD="cross" - fi - - BUILD_FEATURES_ARGS="${{ inputs.features }}" - NO_DEFAULT_FEATURES="" - if [ "${{ inputs.no-default-features }}" == "true" ]; then - NO_DEFAULT_FEATURES="--no-default-features" - fi - - CRATE_TYPES="" - if [ "${{ inputs.build-library }}" == "true" ]; then - CRATE_TYPES="--crate-type cdylib --crate-type staticlib" - fi - - export RUSTFLAGS="${{ inputs.additional-rustflags }} -Zlocation-detail=none -C lto=fat" - if [ "${{ inputs.abort-on-panic }}" == "true" ]; then - export RUSTFLAGS="$RUSTFLAGS -C panic=abort" - BUILD_STD_ARGS="-Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort" - else - BUILD_STD_ARGS="-Z build-std=std" - fi - - # Handle PGO - if [ "${{ inputs.use-pgo }}" == "true" ]; then - rustup component add llvm-tools-preview - - # Normalize pgo-project-path for PGO, because it doesn't handle double slashes - # (user error) well. - PGO_PROJECT_PATH="${{ inputs.pgo-project-path }}" - PGO_PROJECT_PATH="${PGO_PROJECT_PATH%/}" # Remove trailing forward slash - PGO_PROJECT_PATH="${PGO_PROJECT_PATH%\\}" # Remove trailing backslash - - # Generate PGO profiling data - RUSTFLAGS_BACKUP="$RUSTFLAGS" - PGO_PROFILES_FOLDER="${GITHUB_WORKSPACE}/${PGO_PROJECT_PATH}/target/pgo-profiles" - export RUSTFLAGS="$RUSTFLAGS -Cprofile-generate=$PGO_PROFILES_FOLDER" - - cd "${GITHUB_WORKSPACE}/${PGO_PROJECT_PATH}" - echo "Flags: $RUSTFLAGS" - echo "$BUILD_CMD +nightly rustc --release $BUILD_STD_ARGS --target ${{ inputs.target }} $CRATE_TYPES --features \"$BUILD_FEATURES_ARGS,pgo\" $NO_DEFAULT_FEATURES" - $BUILD_CMD +nightly test --bench ${{ inputs.pgo-benchmark-name }} --release --target ${{ inputs.target }} --features "$BUILD_FEATURES_ARGS,pgo" $NO_DEFAULT_FEATURES - - # Check if .profraw files were created - echo "Profiles Folder: $PGO_PROFILES_FOLDER" - ls "$PGO_PROFILES_FOLDER" - if [ ! -f "$PGO_PROFILES_FOLDER/"*.profraw ]; then - echo "::error::No .profraw files were created during the PGO run. PGO data generation failed." - exit 1 + for subdir in "$dir"/*; do + if [ -d "$subdir" ]; then + base=$(basename "$subdir") + zip -r "$dir/$base.zip" "$subdir" + rm -r "$subdir" fi - - # Merge the PGO profiles - # This is tricky, llvm-profdata isn't in $PATH, so we need to find it ourselves. - target_libdir=$(rustc --print target-libdir) - bin_dir=$(dirname "$target_libdir")/bin - llvm_profdata_path=$(find "$bin_dir" -name "llvm-profdata*" | head -n 1) - - MERGED_PGO_PROFILE=$PGO_PROFILES_FOLDER/merged.profdata - $llvm_profdata_path merge -o "$MERGED_PGO_PROFILE" "$PGO_PROFILES_FOLDER" - - # Assert merged.profdata is not empty - echo "Merged Profiles Folder: $PGO_PROFILES_FOLDER" - ls "$PGO_PROFILES_FOLDER" - if [ ! -s "$MERGED_PGO_PROFILE" ]; then - # Note: RUSTFLAGS can't handle spaces, so we're kinda screwed if the path up to here - # has spaces in it. - echo "::error::merged.profdata is empty. PGO data generation failed." - exit 1 - fi - - # Use the generated PGO profiling data to perform an optimized build - export RUSTFLAGS="$RUSTFLAGS_BACKUP -C llvm-args=-pgo-warn-missing-function -C profile-use=$MERGED_PGO_PROFILE" - fi - - # Build the final project - cd "${GITHUB_WORKSPACE}/${{ inputs.rust-project-path }}" - echo "Flags: $RUSTFLAGS" - echo "$BUILD_CMD +nightly rustc --release $BUILD_STD_ARGS --target ${{ inputs.target }} $CRATE_TYPES --features \"$BUILD_FEATURES_ARGS\" $NO_DEFAULT_FEATURES" - $BUILD_CMD +nightly rustc --release $BUILD_STD_ARGS --target ${{ inputs.target }} $CRATE_TYPES --features "$BUILD_FEATURES_ARGS" $NO_DEFAULT_FEATURES - - echo "PWD: $(pwd)" - echo "Build Dir: ${GITHUB_WORKSPACE}/${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release" - ls "${GITHUB_WORKSPACE}/${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release" + done + ls -A ./${{ inputs.artifacts-directory }} - - name: Upload binary artifacts - if: inputs.upload-artifacts == 'true' && inputs.build-library != 'true' - uses: actions/upload-artifact@v4 - with: - name: ${{ inputs.crate-name }}-${{ inputs.target }}-${{ inputs.features }} - path: | - ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/${{ inputs.crate-name }}* - !${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/${{ inputs.crate-name }}*.d - - - name: Upload library artifacts - if: inputs.upload-artifacts == 'true' && inputs.build-library == 'true' - uses: actions/upload-artifact@v4 + - name: Create GitHub release + if: inputs.create-release == 'true' + uses: softprops/action-gh-release@v2 with: - name: C-Library-${{ inputs.target }}-${{ inputs.features }} - path: | - ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.a - ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.so - ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.lib - ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.dll - ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.pdb - ${{ inputs.rust-project-path }}/target/${{ inputs.target }}/release/*.dylib + files: | + ${{ inputs.artifacts-directory }}/* - - name: Run Tests and Coverage - if: inputs.run-tests-and-coverage == 'true' - uses: Reloaded-Project/devops-rust-test-and-coverage@v1 - with: - rust-project-path: ${{ inputs.rust-project-path }} - rust-toolchain: nightly - target: ${{ inputs.target }} - install-rust-toolchain: false - setup-rust-cache: false - upload-coverage: ${{ inputs.upload-coverage-to-codecov }} - codecov-token: ${{ inputs.codecov-token }} - features: ${{ inputs.features }} - no-default-features: ${{ inputs.no-default-features }} - use-cross: ${{ inputs.use-cross }} \ No newline at end of file + - name: Publish to crates.io + if: inputs.crates-io-token != '' + shell: bash + run: | + while IFS= read -r path; do + echo "Publishing Rust package at path: $path" + cargo publish --token ${{ inputs.crates-io-token }} ${{ inputs.additional-publish-params }} --manifest-path "$path/Cargo.toml" + done <<< "${{ inputs.rust-project-paths }}" \ No newline at end of file