Skip to content

[PROF-15176] Add automated GitHub release workflow + bump to 0.3.0#62

Merged
r1viollet merged 12 commits into
mainfrom
r1viollet/release-workflow
Jun 23, 2026
Merged

[PROF-15176] Add automated GitHub release workflow + bump to 0.3.0#62
r1viollet merged 12 commits into
mainfrom
r1viollet/release-workflow

Conversation

@r1viollet

@r1viollet r1viollet commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds an automated release workflow and bumps to 0.3.0. Pushing a vX.Y.Z tag now produces a draft GitHub Release with dd-win-prof.zip attached.

Changes:

  • .github/workflows/release.yml — on v*.*.* tag push (or workflow_dispatch against an existing tag), checks Version.h matches the tag, builds Release on windows-2022 (same cmake invocation as test.yml + -DDD_WIN_PROF_BUILD_OBFUSCATION=ON), runs cmake --install, zips, and creates a draft release with auto-generated notes.
  • .github/chainguard/self.github.release.publish.sts.yaml — Octo-STS trust policy. The repo's default GITHUB_TOKEN is capped to contents: read, so the workflow federates an elevated token via DataDog/dd-octo-sts-action@96a25462... (v1.0.4, pinned) and uses it for gh release create. Policy is narrowly scoped to a vX.Y.Z tag push or a workflow_dispatch from main, locked to release.yml, granting contents: write only. Naming and shape follow the dd-octo-sts conventions ({source}.{environment}.{action}.{context}.sts.yaml).
  • CMake install() rules in src/dd-win-prof/, obfuscation/ObfSymbols/, and the top-level CMakeLists.txt. The workflow just drives them — file paths and on-disk layout are owned by CMake, not the YAML. Reproducible locally with cmake --install build --config Release --prefix .\stage\dd-win-prof.
  • OSS compliance: ship LICENSE, NOTICE, LICENSE-3rdparty.csv, and the tracked licenses/ directory in the zip. v0.2.0 didn't have these.
  • Suppress upstream install() rules for googletest (INSTALL_GTEST=OFF) and spdlog (SPDLOG_INSTALL=OFF) so they don't pollute the release prefix.
  • scripts/check-version.ps1 — extracted the tag-vs-version.h check so it's runnable locally (.\scripts\check-version.ps1 -Tag v0.3.0).
  • src/dd-win-prof/version.h bumped 0.1.00.3.0 (v0.2.0 shipped without bumping; the new assertion prevents the drift recurring).
  • README: short Packaging a release + Cutting a release sections.

Final zip layout (strict superset of v0.2.0 — outer dd-win-prof/ wrapper preserved, no binaries removed, licensing files added):

dd-win-prof/
├── LICENSE  NOTICE  LICENSE-3rdparty.csv
├── licenses/{MIT.txt, BSD-3-Clause.txt}
├── Profiler/{dd-win-prof.dll, .lib, .pdb, .h, datadog_profiling_ffi.dll, .pdb}
└── Obfuscation/ObfSymbols.exe

Motivation

v0.1.0 and v0.2.0 were built and packaged manually, and v0.2.0 shipped with a stale version.h and no LICENSE/NOTICE in the zip. Automating the release closes both gaps and gives us a reproducible artifact pipeline. Packaging logic lives in CMake so anyone can repro the release tree locally — the workflow's role is just trigger + upload.

Ticket: PROF-15176 (parent epic: PROF-14955).

Testing

  • Existing test.yml CI runs unchanged on this PR.
  • cmake --install build --config Release --prefix .\stage\dd-win-prof reproduces the expected layout locally on Windows.

End-to-end validation of the tag-triggered path (Octo-STS federation + gh release create) happens on the v0.3.0 tag push.

Checklist

  • Code follows existing style
  • Documentation updated (README packaging + releasing sections)
  • No breaking changes

Adds .github/workflows/release.yml triggered on v*.*.* tag push:
- Validates tag matches Version.h before doing any work
- Builds Release on windows-2022 (same cmake invocation as test.yml,
  plus -DDD_WIN_PROF_BUILD_OBFUSCATION=ON)
- Assembles dd-win-prof.zip matching v0.2.0's hand-packaged layout
- Creates a draft GitHub Release with auto-generated notes and uploads
  the zip; left as draft so the maintainer can edit notes and publish

Also bumps src/dd-win-prof/version.h from 0.1.0 to 0.3.0; v0.2.0 was
released without bumping this and the new workflow's assertion step
prevents that drift recurring.

Pattern modeled on DataDog/java-profiler's gh_release.yml +
update_assets.yml, collapsed into a single workflow since dd-win-prof
builds artifacts in CI rather than fetching from a registry.
…ase zip

Apache 2.0 §4 requires distributing LICENSE + NOTICE alongside any
redistributed binary. The release zip ships libdatadog's
datadog_profiling_ffi.dll (Apache 2.0) and dd-win-prof.dll, which
statically links spdlog + bundled fmt (MIT). Add to the zip:

  LICENSE                  (dd-win-prof, Apache 2.0)
  NOTICE                   (dd-win-prof attribution)
  LICENSE-3rdparty.csv     (canonical manifest)
  licenses/libdatadog-LICENSE
  licenses/spdlog-LICENSE
The release workflow's staging step was doing build-system-shaped work:
knowing where each artifact lives in the build tree, where headers and
license files live in the source tree, and what the on-disk layout of
the release should be. Move all of that into install() rules:

- src/dd-win-prof/CMakeLists.txt: install dd-win-prof.{dll,lib,pdb,h}
  + the vendored datadog_profiling_ffi.{dll,pdb} under Profiler/.
  Config-aware via $<LOWER_CASE:$<CONFIG>> so 'cmake --install --config
  Debug' would pick up the debug FFI variant.
- obfuscation/ObfSymbols/CMakeLists.txt: install ObfSymbols.exe under
  Obfuscation/.
- CMakeLists.txt: install LICENSE, NOTICE, LICENSE-3rdparty.csv at the
  package root, plus the upstream libdatadog and spdlog license texts
  under licenses/. Gated on DD_WIN_PROF_IS_TOPLEVEL so consuming
  projects that pull dd-win-prof in via add_subdirectory don't inherit
  our top-level license install rules.

release.yml's 'Stage release assets' step collapses to a single
'cmake --install ... --prefix <stage>/dd-win-prof' + Compress-Archive.
Anyone with the repo can now reproduce the exact release layout locally
with 'cmake --install build --prefix foo/'.
@r1viollet

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0344765825

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread CMakeLists.txt Outdated
Two new subsections under 'How to build dd-win-prof':

- 'Packaging a release' documents the cmake --install invocation that
  reproduces the release zip layout locally, and points at the
  install() rules as the source of truth for the layout.
- 'Cutting a release' walks through the version bump + tag push flow
  that drives release.yml, including the workflow_dispatch escape
  hatch for re-uploading assets without re-tagging.
cmake --install for the release package was failing because
googletest's own install rules tried to install gtest.lib from a path
that doesn't exist with our build layout, and would have also dropped
gtest/spdlog headers into our release prefix regardless. Set the
upstream-provided knobs (INSTALL_GTEST=OFF, SPDLOG_INSTALL=OFF) before
FetchContent_MakeAvailable so only our own install() rules contribute
to the release zip.
The previous install rules referenced third-party/libdatadog-x64-windows/LICENSE
and third-party/spdlog/LICENSE -- paths that only exist as stale local
vendoring leftovers, not in the git index. On a clean checkout cmake
--install failed with 'file INSTALL cannot find'.

The repo already has a tracked, canonical license layout: LICENSE +
NOTICE at the root, LICENSE-3rdparty.csv enumerating third-party
components, and licenses/{MIT,BSD-3-Clause}.txt with the corresponding
license texts. Install the whole licenses/ directory into the package
instead.
@r1viollet
r1viollet marked this pull request as ready for review June 19, 2026 15:00
@r1viollet
r1viollet requested a review from chrisnas as a code owner June 19, 2026 15:00
The inline pwsh block in release.yml was not runnable locally. Move
the parsing + comparison into scripts/check-version.ps1 -Tag <vX.Y.Z>
and have the workflow invoke it. Developers can now run the same
check before tagging:

    .\scripts\check-version.ps1 -Tag v0.3.0
The repo's default GITHUB_TOKEN is org-capped to 'contents: read', so
'gh release create' would 403 even with workflow-declared
'contents: write'. Federate an elevated token via Octo-STS instead.

- .github/chainguard/self.release.build-and-release.sts.yaml: trust
  policy. Matches a vX.Y.Z tag push or workflow_dispatch from main,
  locked to .github/workflows/release.yml as the calling workflow,
  granting contents: write.
- release.yml: drop contents: write from the job-level permissions
  (no longer needed on GITHUB_TOKEN), add id-token: write so the runner
  can mint the OIDC token, add a DataDog/dd-octo-sts-action step, and
  use ${{ steps.octo-sts.outputs.token }} for the gh release calls.

Naming convention and policy shape mirror DataDog/java-profiler's
existing octo-sts integrations (approve-trivial, dependabot-automerge).
@r1viollet
r1viollet marked this pull request as draft June 19, 2026 16:05
Per the dd-octo-sts authoritative guide:

- Rename file to follow {source}.{environment}.{action}.{context} naming:
  self.release.build-and-release.sts.yaml
  -> self.github.release.publish.sts.yaml
- Add 'Policy for: ...' header comment so reviewers immediately see the
  source workflow and job.
- Use [0-9]+ instead of \d+ in patterns (matches guide examples).
- Add the 'repository' claim alongside event_name / ref / job_workflow_ref
  for defense in depth, and tighten job_workflow_ref to the same ref set
  as subject_pattern.
- Keep claim_pattern keys in alphabetical order per the style guide.

dd-octo-sts-action is already pinned to the latest release (v1.0.4,
SHA 96a25462dbcb10ebf0bfd6e2ccc917d2ab235b9a).
@r1viollet
r1viollet marked this pull request as ready for review June 19, 2026 16:12
git tag -s produces a signed annotated tag using the SSH key
configured globally (gpg.format=ssh). Lightweight unsigned tags are
discouraged for releases; downstream consumers can verify provenance
from the signature.
main always sits at the version about to be released, so the tag
points at main as-is. The version.h bump becomes a follow-up PR that
moves main onto the next dev version, rather than a precondition for
the tag. This keeps the path-to-release as short as 'tag and push'.
@r1viollet

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e10cb06b75

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

$zipPath = Join-Path $stagingRoot "dd-win-prof.zip"
Compress-Archive -Path $pkgDir -DestinationPath $zipPath

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude the staging folder from the release archive

On the Windows release job, Compress-Archive -Path $pkgDir archives the directory itself; Microsoft documents that a Path without a wildcard includes the root directory, while C:\Reference\* excludes it (https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/compress-archive#example-3-compress-a-directory-that-includes-the-root-directory). Because $pkgDir is already named dd-win-prof, the uploaded dd-win-prof.zip will extract to dd-win-prof\LICENSE, dd-win-prof\Profiler\... instead of the documented v0.2.0-compatible root layout (LICENSE, Profiler\...), so consumers/scripts that unzip the asset and look for files at the archive root will fail.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we have the same structure as before. Not an issue.

Comment thread src/dd-win-prof/version.h

#define DLL_VERSION_MAJOR 0
#define DLL_VERSION_MINOR 1
#define DLL_VERSION_MINOR 3

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep VERSIONINFO in sync with the bumped release

When the v0.3.0 release is built, this bump updates the profiler header and lets scripts/check-version.ps1 pass, but the Windows resource compiled into dd-win-prof.dll still hard-codes 0.2.0.0 in src/dd-win-prof/Resource.rc for FILEVERSION, PRODUCTVERSION, and the string values. Users or deployment tooling that inspect the DLL's file/product version will see a v0.2.0 binary inside the v0.3.0 release artifact, and the new release gate won't catch that drift because it only parses version.h.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, this is real and needs a follow up PR

@chrisnas chrisnas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@r1viollet
r1viollet merged commit 769c4e3 into main Jun 23, 2026
8 checks passed
@r1viollet
r1viollet deleted the r1viollet/release-workflow branch June 23, 2026 10:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants