DreamShaderLang
Plugin referenceContributing

Release

Release

Release

DreamShader » Contributing » Release

The tag conventions the release workflow enforces, what the workflow does, and exactly what the published archive contains.

Declared in.github/workflows/release.yml — the only workflow in the repository
KindGitHub Actions workflow
Runnerwindows-latest; every step is pwsh
Permissionscontents: write
Version source of truthDreamShader.uplugin → VersionName and IsBetaVersion

Synopsis

git tag v<major>.<minor>.<patch>[b]
git push origin v<major>.<minor>.<patch>[b]

The trailing b marks a beta. The workflow also accepts a manual run:

workflow_dispatch(version = [<slug>], prerelease = { true | false })

version is optional and, when given, must equal the slug the descriptor implies (a leading v is stripped before the comparison). prerelease defaults to false and can only add the pre-release flag, never remove it.

Tag conventions

KindTag patternExampleSlugPre-release
Stablev*.*.*v1.5.01.5.0no, unless the dispatch input forces it
Betav*.*.*bv1.5.0b1.5.0byes

The tag is derived, not chosen: the workflow computes it from the descriptor and refuses to run if the pushed tag differs. Tagging is therefore a two-step change — edit DreamShader.uplugin first, commit, then tag.

Version derivation

StepRule
1Read VersionName from DreamShader.uplugin. Empty is an error.
2It must match ^\s*([0-9]+\.[0-9]+\.[0-9]+). A decorated name is fine — "1.5.0 - Beta" yields the base 1.5.0.
3Beta when IsBetaVersion is true or VersionName matches (?i)beta.
4Slug = base version, plus a b suffix when beta.
5Tag = v + slug.
6On a tag push, the pushed tag must equal the derived tag. On a manual run, a non-empty version input must equal the slug.
7Export DREAMSHADER_VERSION, DREAMSHADER_BASE, DREAMSHADER_SLUG, DREAMSHADER_TAG and DREAMSHADER_PRERELEASE for the later steps.

For the current descriptor — VersionName 2.2.0, IsBetaVersion false, Version 220 — this yields base 2.2.0, slug 2.2.0, tag v2.2.0, pre-release false, and the archive DreamShader-2.2.0.zip.

[!NOTE] Version (the integer, 180) is never read by the workflow. It is the descriptor's own numeric version and is only meaningful to Unreal. Bump it alongside VersionName by hand.

Workflow steps

#StepWhat it does
1Checkoutactions/checkout@v4 with fetch-depth: 0
2Resolve release versionThe seven rules above; throws on any mismatch
3Package pluginStages the shipped items and zips them (see below)
4Download latest VSCode extension release assetsgh release download --repo TypeDreamMoon/dreamshader-language-support --pattern '*' into artifacts/vscode-extension; throws when nothing is downloaded
5Build release notesExtracts this version's CHANGELOG.md section and assembles the body
6Publish GitHub ReleaseCreates the release, or updates it if the tag already has one

Archive contents

The staging directory is <RUNNER_TEMP>/DreamShaderRelease/DreamShader/, and it is compressed to artifacts/DreamShader-<slug>.zip. The archive's single top-level entry is the folder DreamShader, which is what the install instructions tell users to drop into Plugins/.

Eleven items are copied. A missing item is skipped rather than failing the release, but it now emits a ::warning:: annotation on the run summary — silence is how three of them stayed out of every archive up to 1.5.0 without anyone noticing.

Shipped
Source/
Resources/
Shaders/(since 1.5.1) DreamShaderBuiltins.ush, so /Plugin/DreamShader/… resolves in an archive install; the Custom Pass shaders under Pass/, without which the DreamShaderPass module's global and mesh-pass shaders do not compile
Content/(since 2.1.2) Localization/DreamShader/ — the .locmeta and the zh-Hans .locres — so the descriptor's LocalizationTargets entry has a translation to load in an archive install
Docs/
.skill/(since 1.5.1) the agent skill set and its driver
DreamShader.uplugin
README.md
README.zh-CN.md(since 1.5.1) — README.md links to it, so the archive's link used to dangle
CHANGELOG.md
LICENSE

Everything else in the repository is absent:

Not shippedConsequence for an archive install
Tests/The fixture corpus is absent; the two data-driven runners enumerate zero sub-tests
Tools/The localization and parity scripts are absent: the built .locres ships, the chain that rebuilds it does not
Config/FilterPlugin.ini is absent. It only holds the stock commented template and declares no packaged files
Images/README artwork is missing, so the readme's images do not render locally
.github/The workflow itself is not redistributed
Binaries/, Intermediate/The archive is source-only; the consumer's first editor launch compiles the four modules

[!NOTE] Up to and including 1.5.0 the archive shipped no Shaders/ folder, so anything resolving /Plugin/DreamShader/... had no file to read in an install made from the release zip. Installs from those archives still need Shaders/DreamShaderBuiltins.ush copied in by hand. See HLSL library.

[!NOTE] From 1.6.0, the first version with a zh-Hans translation, up to and including 2.1.1, the archive shipped no Content/ folder. It was never on the list, so no warning flagged it either. In an install made from one of those zips the descriptor's LocalizationTargets entry finds nothing to load, and DreamShader's editor text stays English even in a zh-Hans editor. Copying Content/Localization/ in by hand from the repository at the matching tag fixes it. Since 2.1.2 the workflow copies Content/ whole, as BuildPlugin does, so anything added under it later ships too. See Localization.

Unlike the list above, this one is not left to a warning. After compressing, the step opens the zip and, for every LocalizationTargets entry in the descriptor, requires Content/Localization/<Name>/<Name>.locmeta and every <culture>/<Name>.locres the repository has for it; a missing one fails the release.

[!NOTE] The archive ships no Binaries/, so the plugin is compiled by the consuming project. That requires a C++ project (or one converted to C++) and a matching engine toolchain — see Contributing for the MSVC caveat on UE 5.3 and 5.4.

Release notes

The body is assembled in this order.

PartContent
Pre-release calloutAdded only for a beta: a warning that APIs and generated-asset layout may still change before the stable base version, with a link to the issue tracker
InstallationThree steps: download DreamShader-<slug>.zip, extract the DreamShader folder into Plugins/, enable DreamShader in Edit ▸ Plugins and restart
Compatibility lineThe literal string Compatible with Unreal Engine 5.3 - 5.8 (Win64).
What's changedThe ## <VersionName> section of CHANGELOG.md, verbatim
AssetsA two-row table: the plugin zip, and *.vsix for the VSCode extension
LinksDocumentation https://shader.toolchain.64hz.cn/, the changelog at the release tag, and the VSCode extension repository

Changelog extraction details:

  • The section is found by matching ^##\s+<VersionName>\b, so the changelog heading must begin with the VersionName exactly as written, decorations and all. Trailing text is fine, which is why ## 1.9.1 - 2026-09-08 matches the current VersionName 1.9.1. The failure runs the other way: a decorated name such as 1.5.0 - Beta is not matched by a bare ## 1.5.0 heading.
  • It ends at the next ## heading.
  • Leading blockquote lines are stripped, so the changelog's own beta note does not duplicate the workflow's pre-release callout.
  • When no matching section exists, the body falls back to a single link to CHANGELOG.md at the release tag. This is silent — a mistyped heading produces a release with no notes rather than a failure.

Publication

SituationAction
No release exists for the taggh release create with the zip and every downloaded VSCode asset
The run is a manual dispatch, not a tag push--target <commit sha> is added so the tag is created on the dispatched commit
A release already exists for the taggh release upload --clobber for the assets, then gh release edit for the title and notes
Beta, or the dispatch input prerelease is true--prerelease on create, or a second gh release edit --prerelease on update

The release title is DreamShader <VersionName> — the name verbatim, decorations and all, for example DreamShader 1.9.1. Assets are the plugin zip followed by every file downloaded from the VSCode extension's latest release, sorted by name.

Diagnostics

Every message the workflow can throw. Runtime substitutions are shown as {Placeholder}.

MessageStepCause
DreamShader.uplugin VersionName is empty.Resolve release versionVersionName is absent or whitespace
DreamShader.uplugin VersionName '{VersionName}' must start with an X.Y.Z version.Resolve release versionVersionName does not begin with three dot-separated integers
Pushed tag '{PushedTag}' does not match the tag derived from DreamShader.uplugin ('{DerivedTag}'). Fix VersionName / IsBetaVersion, or retag.Resolve release versionThe tag and the descriptor disagree — usually a forgotten b, or a bump that was tagged before it was committed
Requested version '{Input}' does not match DreamShader.uplugin ('{Slug}').Resolve release versionA manual run passed a version input that is not the derived slug
No assets were downloaded from TypeDreamMoon/dreamshader-language-support latest release.Download VSCode assetsThe extension repository's latest release has no assets, or the download failed

Each step sets $ErrorActionPreference = 'Stop', so any other PowerShell failure aborts the job as well.

Notes

  • The workflow never builds the plugin. It stages files and publishes them; compilation happens on the consumer's machine. Run RunUAT BuildPlugin yourself before tagging — see Contributing.
  • The workflow never runs the automation suite either. See Testing.
  • Re-running the workflow for an existing tag is safe: assets are clobbered and the notes are rewritten from the current CHANGELOG.md.
  • Deleting a tag that already has a release turns that release into a draft. Re-pushing the tag re-runs the workflow, but the workflow edits the existing release rather than creating one, so it stays a draft — invisible to users, and the previous version keeps the Latest badge. Finish with gh release edit v<slug> --draft=false --latest. Observed while re-cutting v1.5.1.
  • The VSCode extension is released from its own repository. The workflow always pulls that repository's latest release, so a plugin release published while the extension is mid-release will carry the previous .vsix.
  • DocsURL in the descriptor points at https://shader.toolchain.64hz.cn/, which is built from Docs/. The Docs/ tree is shipped in the archive, so the manual is also available offline next to the plugin.

Example

Cutting the 1.5.1 stable release:

# 1. Bump the descriptor: VersionName = "1.5.1", IsBetaVersion = false, Version = 151.
# 2. Add a matching "## 1.5.1 - 2026-08-02" section to CHANGELOG.md, and the version's section
#    to Docs/changelog/dreamshader.md (the manual's release notes, written by hand).
git add DreamShader.uplugin CHANGELOG.md Docs/changelog/dreamshader.md
git commit -m "Release 1.5.1"
git push

# 3. Tag exactly what the descriptor implies: base 1.5.1, no beta 'b'.
git tag v1.5.1
git push origin v1.5.1

Published result:

release      DreamShader 1.5.1
tag          v1.5.1
assets       DreamShader-1.5.1.zip
             <every asset from the latest dreamshader-language-support release, e.g. *.vsix>
zip layout   DreamShader/Source/  DreamShader/Resources/  DreamShader/Shaders/
             DreamShader/Docs/  DreamShader/.skill/
             DreamShader/DreamShader.uplugin
             DreamShader/README.md  DreamShader/README.zh-CN.md
             DreamShader/CHANGELOG.md  DreamShader/LICENSE

See also

On this page