Skip to content
CysharpPublic

About

No description, website, or topics provided.

Resources

Stars

66 stars

Watchers

2 watching

Forks

Repository files navigation

cysharp actions lint

Test benchmark-runnable Test check-metas Test checkout Test clean-packagejson-branch Test create-release Test setup-dotnet Test update-packagejson

Actions

Reusable workflows and composite actions maintained for Cysharp repositories.

This README reflects the current public definitions under .github/workflows and .github/actions. Test and maintenance workflows prefixed with _ are intentionally omitted here.

📖 Table of Contents

Reusable workflows

Workflow Purpose Key inputs / notes
actions-timeline Post workflow timing information using Kesin11/actions-timeline. Requires secrets.github-token.
benchmark-loader Authorize benchmark requests and generate a benchmark execution matrix from a loader config. Inputs: benchmark-name-prefix, benchmark-config-path. Outputs: is-benchmarkable, matrix.
benchmark-execute Provision benchmark infrastructure, execute benchmark matrix entries, and update PR/issue progress comments. Inputs include benchmark-name, benchmark-config-path, branch. Requires the benchmark environment and 1Password/Azure secrets.
benchmark-cleanup Clean benchmark environments on schedule or on demand. Inputs: state, try-redeploy, no-delete. Scheduled hourly in this repo.
clean-packagejson-branch Delete a temporary branch created by release/update automation. Only deletes non-default branches created by github-actions[bot]. Input: branch.
create-release Validate a tag, create a GitHub release and optionally upload release assets. Inputs include commit-id, tag, dry-run, release-upload, release-asset-path, download-run-id.
dd-event-post Post an event to Datadog, typically for PR merge notifications. Inputs include title, text, event, additional-tags, alert-type.
increment-version Increment a semantic version string and expose the computed version. Inputs: tag, type, optional prefix, suffix, ref. Output: version.
prevent-github-change Fail PRs from forks when they modify .github/**/*.yml or .github/**/*.yaml. Intended for policy enforcement around GitHub configuration changes.
pr-harness Run protected .github/ checks, dependency review, and forbidden Unicode checks. Trigger on edited as well as code-changing PR events so title/body edits are rescanned.
stale-issue Mark and close stale issues and PRs using actions/stale. Current defaults: stale after 180 days, close 30 days later.
update-packagejson Normalize a release tag, update version-bearing files, optionally run project-specific dotnet run -- --version {tag}, and push the result. Supports package.json, plugin.cfg, and Directory.Build.props. Outputs: branch-name, is-branch-created, sha.
validate-release Validate Git tag syntax, NuGet version syntax and release ordering before version updates or builds. Input: tag. Outputs: original tag and version with the leading v removed. Requires only contents: read.

Usage examples

actions-timeline

jobs:
  timeline:
    uses: Cysharp/Actions/.github/workflows/actions-timeline.yaml@main
    secrets:
      # actions-timeline.yaml requires this exact secret name.
      github-token: ${{ secrets.GITHUB_TOKEN }}

benchmark-loader + benchmark-execute

jobs:
  loader:
    uses: Cysharp/Actions/.github/workflows/benchmark-loader.yaml@main
    with:
      # Prefix is used to construct benchmark environment names.
      # MagicOnion uses issue/run context to avoid name collisions.
      benchmark-name-prefix: myrepo-pr-${{ github.event.number }}
      # Loader config path consumed by benchmark-loader2matrix.
      benchmark-config-path: .github/benchmark-loader.yaml

  benchmark:
    needs: [loader]
    # loader output is a string ('true'/'false'), compare explicitly.
    if: ${{ needs.loader.outputs.is-benchmarkable == 'true' }}
    strategy:
      fail-fast: false
      # Matrix JSON is produced by benchmark-loader output.
      matrix: ${{ fromJson(needs.loader.outputs.matrix) }}
    uses: Cysharp/Actions/.github/workflows/benchmark-execute.yaml@main
    with:
      # Key names come from your loader config output schema.
      benchmark-name: ${{ matrix.benchmark-name }}
      benchmark-config-path: ${{ matrix.benchmark-config-path }}
      branch: ${{ matrix.branch }}
    # benchmark-execute needs Azure/1Password-related secrets.
    secrets: inherit

benchmark-cleanup

jobs:
  cleanup:
    uses: Cysharp/Actions/.github/workflows/benchmark-cleanup.yaml@main
    with:
      # Failed/Succeeded/All depending on your cleanup policy.
      state: Failed
      # Scheduled runs can optionally redeploy before cleanup.
      try-redeploy: false
      # Keep false for normal cleanup (true means dry-maintenance mode).
      no-delete: false

clean-packagejson-branch

jobs:
  cleanup:
    permissions:
      # Required because the workflow deletes remote branches.
      contents: write
    uses: Cysharp/Actions/.github/workflows/clean-packagejson-branch.yaml@main
    with:
      # Usually pass update-packagejson output branch-name.
      branch: test-release/1.2.3

create-release

jobs:
  create-release:
    permissions:
      contents: write
    uses: Cysharp/Actions/.github/workflows/create-release.yaml@main
    with:
      # Empty means current checked out commit.
      commit-id: ""
      # Raw tag like 1.2.3 (workflow validates/normalizes internally).
      tag: ${{ inputs.tag }}
      # true keeps dry-run behavior and cleanup path.
      dry-run: ${{ inputs.dry-run }}
      # Guard to prevent accidentally releasing older tags.
      require-validation: true
      # If true, release-asset-path must be provided.
      release-upload: true
      release-asset-path: |
        ./MyUnityPackage/MyUnityPackage.unitypackage
      # v{0} -> v1.2.3, {0} -> 1.2.3.
      release-format: v{0}
      # Empty means download artifacts from current run.
      download-run-id: ""

commit-id must be the SHA used by the build jobs (the output SHA of update-packagejson when used). Existing lightweight and annotated tags must resolve to that SHA. An existing release causes failure. The workflow calls prepare-release using the existing CLI resolution (the downloaded action binary, or dotnet run as a fallback) and records resource ownership outside the artifact directory; dry runs and failures invoke cleanup-release using that journal. Cleanup preserves pre-existing tags and refuses to delete changed tags or published releases. Dry runs still create a draft and upload requested assets, then clean up immediately. Do not manually modify or publish a draft while its creating job is running.

dd-event-post

jobs:
  post-dd-event:
    # Typical trigger pattern: only post when PR was actually merged.
    if: ${{ github.event.pull_request.merged == true }}
    uses: Cysharp/Actions/.github/workflows/dd-event-post.yaml@main
    with:
      # Keep consistent with dashboard aggregation keys/tags.
      event: pr-merged
      alert-type: info
    # Required because workflow loads DD_API_KEY via 1Password.
    secrets: inherit

increment-version

jobs:
  new-version:
    uses: Cysharp/Actions/.github/workflows/increment-version.yaml@main
    with:
      # Use default branch when you want to continue development after release.
      ref: ${{ github.event.repository.default_branch }}
      # Released tag to increment from.
      tag: 1.2.3
      # major | minor | patch
      type: patch
      prefix: ""
      # Common post-release convention.
      suffix: -dev

pr-harness

name: PR Harness

on:
  pull_request:
    # `edited` is required to rescan PR title/body changes.
    types: [opened, synchronize, reopened, edited]

jobs:
  pr-harness:
    permissions:
      contents: read
      pull-requests: read
    uses: Cysharp/Actions/.github/workflows/pr-harness.yaml@main

The Unicode check is implemented by the CysharpActions scan-pr-unicode CLI command and invoked directly from pr-harness; there is no standalone Unicode workflow or composite action. The checked-in Linux binary is updated only by the release workflow. It scans the PR title, PR body, changed file names, and the complete contents of changed .cs and .csx files in the checked-out working tree. Changed paths are determined by diffing GitHub's test merge commit (refs/pull/<number>/merge) against its first parent, the current base branch tip, so only the merge commit and its two parents (fetch-depth: 2) are required even after the base branch advances. The checkout must be that merge commit, and its second parent must match the event's PR head. File contents are read from the checked-out merge result. C# source rejects symbolic links, raw Unicode format/default-ignorable characters, controls, forbidden \uXXXX / \UXXXXXXXX escapes, and non-ASCII spaces regardless of whether they occur in code, comments, strings, or test data. In addition, every tracked .cs and .csx path is checked for Git symbolic-link mode, including paths not changed by the PR. Other file contents are not scanned. Tests that intentionally need these values should construct them numerically, for example with char.ConvertFromUtf32(0x200B).

update-packagejson

jobs:
  update-packagejson:
    permissions:
      actions: read
      # Required because this workflow can commit/push version updates.
      contents: write
    uses: Cysharp/Actions/.github/workflows/update-packagejson.yaml@main
    with:
      # Keep checkout target explicit (MagicOnion uses github.ref/default branch).
      ref: ${{ github.ref }}
      file-path: |
        # Supported: package.json / plugin.cfg / Directory.Build.props
        ./src/MyUnityProject/package.json
        ./addons/MyPlugin/plugin.cfg
        ./Directory.Build.props
      # Release tag to propagate into version files.
      tag: ${{ inputs.tag }}
      require-validation: true
      # true if your default branch requires GitHub App authentication.
      use-bot-token: false
      # true writes to test-release/{tag} branch instead of target ref.
      dry-run: false
      dotnet-run-path: |
        # Optional hook; workflow always passes: -- --version {tag}
        ./tools/VersionOutput/VersionOutput.csproj
      additional-commit-path: |
        # Explicit allow-list for files generated outside file-path by dotnet-run-path.
        # Files outside file-path and this list are never committed.
        ./tools/VersionOutput/version.txt
jobs:
  cleanup:
    # Branch cleanup is only needed when dry-run created a temp branch.
    if: ${{ needs.update-packagejson.outputs.is-branch-created == 'true' }}
    needs: [update-packagejson]
    permissions:
      contents: write
    uses: Cysharp/Actions/.github/workflows/clean-packagejson-branch.yaml@main
    with:
      # Output of update-packagejson workflow.
      branch: ${{ needs.update-packagejson.outputs.branch-name }}

validate-release

jobs:
  validate-release:
    permissions:
      contents: read
    uses: Cysharp/Actions/.github/workflows/validate-release.yaml@main
    with:
      tag: ${{ inputs.tag }}

  build:
    needs: [validate-release]
    permissions:
      contents: read
    runs-on: ubuntu-24.04
    timeout-minutes: 10
    steps:
      - uses: Cysharp/Actions/.github/actions/checkout@main
      - uses: Cysharp/Actions/.github/actions/setup-dotnet@main
      - run: dotnet build -c Release -p:Version="$VERSION"
        env:
          VERSION: ${{ needs.validate-release.outputs.version }}

This workflow calls the validate-release CLI, running the current source in Cysharp/Actions and the distributed binary for callers. It exposes tag unchanged and version with one leading v removed (for example, v1.2.3 becomes 1.2.3). It queries releases in the calling repository with its GITHUB_TOKEN; no inherited secrets or write permissions are needed. Validation failures fail the job and block dependent jobs.

It validates Git ref syntax and NuGet version syntax and rejects versions older than the latest release using NuGet version ordering. MagicOnion skips only the ordering check to support multiple release lines. Tag-to-build SHA equality is checked later by create-release, after version updates and builds.

Composite actions

Action Purpose Key inputs / notes
benchmark-progress-comment Post or update a benchmark progress comment on an issue or PR. Inputs: comment, state, title, update. No-op when the event has no issue number.
benchmark-runnable Authorize whether a GitHub user may trigger benchmark execution. Input: username. Output: authorized. Current allowlist is maintained in the action itself.
check-metas Fail or report when untracked Unity .meta files exist. Inputs: directory, optional exit-on-error. Output: meta-exists.
checkout SHA-pinned wrapper around actions/checkout. Mirrors most actions/checkout inputs while centralizing the pinned version.
download-artifact SHA-pinned wrapper around actions/download-artifact. Supports name, path, pattern, merge-multiple, github-token, repository, run-id.
publish-nuget Download, validate and publish NuGet packages using OIDC in the caller's job. Required: artifact-name, user, version. Linux X64/ARM64. Optional: dotnet-version (9.0.x), include-symbols (true), skip-duplicate (true).
publish-crates Validate the crate version and publish using OIDC. Required: manifest-path, version. Caller provides the release checkout, Cargo, jq and id-token: write.
setup-dotnet Install one or more .NET SDKs and configure CI-friendly environment variables. Defaults to .NET 6.0.x through 10.0.x. Optional dotnet-quality, skip-env.
unity-builder SHA-pinned wrapper around game-ci/unity-builder. Inputs include projectPath, unityVersion, targetPlatform, buildMethod, customParameters, versioning.
upload-artifact SHA-pinned wrapper around actions/upload-artifact. Default if-no-files-found is error, not warn.

Action examples

benchmark-progress-comment

steps:
  # This action posts comments only for issue/PR events with issue.number.
  - uses: Cysharp/Actions/.github/actions/benchmark-progress-comment@main
    with:
      comment: "Benchmark started"
      state: running
      title: "Benchmark"
      # "true" edits latest benchmark comment; "false" appends a new one.
      update: "true"

benchmark-runnable

steps:
  - id: auth
    uses: Cysharp/Actions/.github/actions/benchmark-runnable@main
    with:
      # Usually github.actor
      username: ${{ github.actor }}

  # authorized output is 'true' or 'false'.
  - run: echo "authorized=${{ steps.auth.outputs.authorized }}"

checkout

steps:
  - id: co
    uses: Cysharp/Actions/.github/actions/checkout@main
    with:
      repository: ${{ github.repository }}
      ref: ${{ github.ref_name }}
      # 0 to fetch full history/tags when versioning logic needs it.
      fetch-depth: 0

  # Wrapper exposes the same useful outputs as actions/checkout.
  - run: echo "checked out ${{ steps.co.outputs.ref }} @ ${{ steps.co.outputs.commit }}"

check-metas

steps:
  - uses: Cysharp/Actions/.github/actions/check-metas@main
    with:
      directory: ./sandbox/Sandbox.Unity
      # Keep true in CI to fail immediately on untracked .meta files.
      exit-on-error: "true"

publish-crates

Run this composite after create-release succeeds, using the same checkout SHA as the builds. The manifest must identify one package, not a virtual workspace.

steps:
  # Check out the release commit before this step.
  - uses: Cysharp/Actions/.github/actions/publish-crates@main
    with:
      manifest-path: csbindgen/Cargo.toml
      version: ${{ needs.validate-release.outputs.version }}

The composite checks the manifest version with cargo metadata, obtains a crates.io OIDC token, and runs cargo publish --manifest-path. It does not add registry queries, checksum comparisons, toolchain installation, or lock-file management. Cargo publication errors, including an already published version, fail the step.

Configure trusted publishing for the calling workflow and give its job contents: read and id-token: write. Skip the entire job during dry runs. Publication across crates.io and NuGet is not atomic. Do not blindly retry a combined publication job after the crate has already been published.

publish-nuget

Add this job after validate-release, the builds, and create-release. If update-packagejson changes sources, use its output SHA for every build and for create-release.

jobs:
  publish-package:
    needs: [validate-release, create-release]
    if: ${{ !inputs.dry-run }}
    permissions:
      contents: read
      id-token: write
    runs-on: ubuntu-24.04
    timeout-minutes: 10
    steps:
      - uses: Cysharp/Actions/.github/actions/publish-nuget@main
        with:
          artifact-name: nuget
          user: ${{ secrets.NUGET_USER }}
          version: ${{ needs.validate-release.outputs.version }}

Configure NuGet trusted publishing for the calling repository's release workflow. The composite installs the publishing SDK and the .NET 9 runtime required by the distributed CLI; no caller checkout is required. It downloads only the named artifact from the current run to an isolated directory. Put .nupkg and optional .snupkg files at the artifact root and retain the artifact long enough for retries (for example, seven days).

Before authentication, the CLI requires at least one .nupkg and checks the nuspec version in every package, including symbols, using NuGet version equality without build metadata. Missing, corrupt or mismatched packages fail the job. Symbols are optional, but invalid symbol packages must be removed during the build. include-symbols: 'false' disables symbol publication, including automatic sibling symbol upload. skip-duplicate: 'true' permits already published versions; it does not prove their contents match. The temporary NuGet API key is used within the composite and is not exposed as an output. Skip the entire caller job during dry runs so OIDC authentication is also skipped.

setup-dotnet

steps:
  - uses: Cysharp/Actions/.github/actions/setup-dotnet@main
    with:
      dotnet-version: |
        10.0.x
      # false also sets CI-friendly env vars (telemetry off, etc.).
      skip-env: "false"

upload-artifact + download-artifact

steps:
  - uses: Cysharp/Actions/.github/actions/upload-artifact@main
    with:
      name: my-artifact
      path: ./artifacts/**
      # Default is already error, but explicit value is clearer in docs.
      if-no-files-found: error

  - uses: Cysharp/Actions/.github/actions/download-artifact@main
    with:
      name: my-artifact
      path: ./downloaded
      # false keeps each artifact in its own directory.
      merge-multiple: "false"

unity-builder

steps:
  # UNITY_* env vars must be set from secrets before this step.
  - uses: Cysharp/Actions/.github/actions/unity-builder@main
    with:
      projectPath: ./sandbox/Sandbox.Unity
      unityVersion: "2022.3.62f1"
      targetPlatform: StandaloneLinux64
      buildMethod: PackageExporter.Export
      customParameters: ""
      # Pass-through to game-ci/unity-builder versioning option.
      versioning: None

Notes

  • secure-checkout and secure-setup-dotnet directories currently exist but do not contain action definitions.
  • validate-tag is implemented by the CysharpActions CLI and used internally by reusable workflows such as create-release and update-packagejson; it is not exposed as a standalone reusable workflow.
  • The repo also contains internal test and maintenance workflows such as _test-*, _toc-generator.yaml, and _update-actions-binaries.yaml.

About

No description, website, or topics provided.

Resources

Stars

66 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages