Skip to content

Commit b47b068

Browse files
Merge pull request #100 from kjldev/expanding-refactorings
feat: use AddEmbeddedAttributeDefinition + changeset release flow
2 parents f25193e + 3fa5886 commit b47b068

14 files changed

Lines changed: 2053 additions & 373 deletions

File tree

.changeset/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Changesets
2+
3+
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4+
with multi-package repos, or single-package repos to help you version and publish your code. You can find the
5+
full documentation for it [in our repository](https://github.com/changesets/changesets).
6+
7+
We have a quick list of common questions to get you started engaging with this project in
8+
[our docs](https://github.com/changesets/changesets/blob/main/docs/common-questions.md). We also have a
9+
[introductory guide](https://github.com/changesets/changesets/blob/main/docs/intro-to-using-changesets.md)
10+
and information about how we [version things](https://github.com/changesets/changesets/blob/main/docs/versioning-policy.md)
11+
for further context.

.changeset/config.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
3+
"changelog": [
4+
"@changesets/changelog-github",
5+
{ "repo": "kjldev/purview-telemetry-sourcegenerator" }
6+
],
7+
"commit": false,
8+
"fixed": [],
9+
"linked": [],
10+
"access": "public",
11+
"baseBranch": "main",
12+
"updateInternalDependencies": "patch",
13+
"ignore": []
14+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"purview-telemetry-sourcegenerator": minor
3+
---
4+
5+
Use `AddEmbeddedAttributeDefinition` to inject `Microsoft.CodeAnalysis.EmbeddedAttribute` via Roslyn's official API, and apply `[global::Microsoft.CodeAnalysis.Embedded]` to all generated marker attribute types.
6+
7+
This ensures generated marker types are invisible to IDE tooling and consumer code, eliminating spurious symbol conflicts. Requires Roslyn 4.14.0+ (ships with Visual Studio 2022 17.14+ and .NET 10 SDK).

.github/workflows/cd.yml

Lines changed: 61 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@ on:
99
branches:
1010
- main
1111
paths:
12-
- .github/workflows/cd.yml
13-
- Justfile
14-
- global.json
1512
- package.json
16-
- benchmarks/**
17-
- samples/**
18-
- src/**
1913

2014
jobs:
2115
release:
@@ -35,36 +29,8 @@ jobs:
3529
with:
3630
fetch-depth: 0
3731

38-
- id: release-trigger
39-
name: Determine whether to publish a release
40-
env:
41-
EVENT_NAME: ${{ github.event_name }}
42-
BEFORE_SHA: ${{ github.event.before }}
43-
CURRENT_SHA: ${{ github.sha }}
44-
shell: bash
45-
run: |
46-
set -euo pipefail
47-
48-
if [[ "${EVENT_NAME}" == "workflow_dispatch" ]]; then
49-
echo "should_release=true" >> "${GITHUB_OUTPUT}"
50-
exit 0
51-
fi
52-
53-
if [[ "${BEFORE_SHA}" == "0000000000000000000000000000000000000000" ]]; then
54-
changed_files="$(git show --name-only --pretty='' "${CURRENT_SHA}")"
55-
else
56-
changed_files="$(git diff --name-only "${BEFORE_SHA}" "${CURRENT_SHA}")"
57-
fi
58-
59-
if grep -Fxq "package.json" <<< "${changed_files}"; then
60-
echo "should_release=true" >> "${GITHUB_OUTPUT}"
61-
else
62-
echo "should_release=false" >> "${GITHUB_OUTPUT}"
63-
fi
64-
6532
- id: version
6633
name: Read release version
67-
if: ${{ steps.release-trigger.outputs.should_release == 'true' }}
6834
shell: bash
6935
run: |
7036
set -euo pipefail
@@ -79,74 +45,62 @@ jobs:
7945
echo "prerelease=false" >> "${GITHUB_OUTPUT}"
8046
fi
8147
82-
- name: Block duplicate version
83-
if: ${{ steps.release-trigger.outputs.should_release == 'true' }}
48+
- id: release-check
49+
name: Check if release already exists
8450
env:
85-
GITHUB_TOKEN: ${{ github.token }}
51+
GH_TOKEN: ${{ github.token }}
8652
RELEASE_TAG: ${{ steps.version.outputs.tag }}
8753
shell: bash
8854
run: |
8955
set -euo pipefail
9056
91-
if git ls-remote --exit-code --tags origin "refs/tags/${RELEASE_TAG}" > /dev/null 2>&1; then
92-
echo "::error::Tag ${RELEASE_TAG} already exists on origin. Refusing to replace an existing release version."
93-
exit 1
94-
fi
95-
96-
release_status="$(
97-
curl -sS \
98-
-o release.json \
99-
-w "%{http_code}" \
100-
-H "Authorization: Bearer ${GITHUB_TOKEN}" \
101-
-H "Accept: application/vnd.github+json" \
102-
"https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/tags/${RELEASE_TAG}"
103-
)"
104-
105-
if [[ "${release_status}" == "200" ]]; then
106-
echo "::error::Release ${RELEASE_TAG} already exists. Refusing to replace an existing release version."
107-
cat release.json
108-
exit 1
109-
fi
110-
111-
if [[ "${release_status}" != "404" ]]; then
112-
echo "::error::Unexpected GitHub API response while checking ${RELEASE_TAG} (HTTP ${release_status})."
113-
cat release.json
114-
exit 1
57+
if gh release view "${RELEASE_TAG}" --repo "${GITHUB_REPOSITORY}" &>/dev/null; then
58+
echo "::notice::Release ${RELEASE_TAG} already exists — skipping."
59+
echo "should_release=false" >> "${GITHUB_OUTPUT}"
60+
else
61+
echo "should_release=true" >> "${GITHUB_OUTPUT}"
11562
fi
11663
117-
rm -f release.json
118-
11964
- name: Set up .NET
65+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
12066
uses: actions/setup-dotnet@v5
12167
with:
12268
global-json-file: ./global.json
12369

12470
- name: Restore dotnet tools
71+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
12572
run: dotnet tool restore
12673

12774
- name: CSharpier format check
75+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
12876
run: dotnet csharpier check .
12977

13078
- name: Restore main solution
79+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
13180
run: dotnet restore ${{ env.MAIN_SOLUTION }}
13281

13382
- name: Build main solution
83+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
13484
run: dotnet build ${{ env.MAIN_SOLUTION }} --no-restore --configuration ${{ env.CONFIGURATION }}
13585

13686
- name: Test main solution
137-
run: dotnet test --solution ${{ env.MAIN_SOLUTION }} --no-build --configuration ${{ env.CONFIGURATION }} --verbosity normal
87+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
88+
run: dotnet test ${{ env.MAIN_SOLUTION }} --no-build --configuration ${{ env.CONFIGURATION }} --verbosity normal
13889

13990
- name: Restore sample solution
91+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
14092
run: dotnet restore ${{ env.SAMPLE_SOLUTION }}
14193

14294
- name: Build sample solution
95+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
14396
run: dotnet build ${{ env.SAMPLE_SOLUTION }} --no-restore --configuration ${{ env.CONFIGURATION }}
14497

14598
- name: Test sample solution
146-
run: dotnet test --solution ${{ env.SAMPLE_SOLUTION }} --no-build --configuration ${{ env.CONFIGURATION }} --verbosity normal
99+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
100+
run: dotnet test ${{ env.SAMPLE_SOLUTION }} --no-build --configuration ${{ env.CONFIGURATION }} --verbosity normal
147101

148102
- name: Pack NuGet artifacts
149-
if: ${{ steps.release-trigger.outputs.should_release == 'true' }}
103+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
150104
env:
151105
PACKAGE_VERSION: ${{ steps.version.outputs.value }}
152106
shell: bash
@@ -165,20 +119,47 @@ jobs:
165119
"/p:RepositoryCommit=${GITHUB_SHA}" \
166120
"/p:COPYRIGHT_YEAR=$(date -u +%Y)"
167121
168-
- name: Create GitHub release
169-
if: ${{ steps.release-trigger.outputs.should_release == 'true' }}
170-
uses: softprops/action-gh-release@v3
171-
with:
172-
tag_name: ${{ steps.version.outputs.tag }}
173-
name: ${{ steps.version.outputs.tag }}
174-
target_commitish: ${{ github.sha }}
175-
generate_release_notes: true
176-
prerelease: ${{ steps.version.outputs.prerelease }}
177-
fail_on_unmatched_files: true
178-
files: |
179-
./artifacts/nuget/*.nupkg
122+
- name: Publish GitHub Release
123+
if: ${{ steps.release-check.outputs.should_release == 'true' }}
124+
env:
125+
GH_TOKEN: ${{ github.token }}
126+
RELEASE_TAG: ${{ steps.version.outputs.tag }}
127+
PRERELEASE: ${{ steps.version.outputs.prerelease }}
128+
shell: bash
129+
run: |
130+
set -euo pipefail
131+
132+
# On any error: delete the draft release and its tag so the next run starts clean.
133+
# Draft releases are never immutable, so this always succeeds.
134+
cleanup() {
135+
echo "::warning::Release failed — cleaning up draft and tag for ${RELEASE_TAG}..."
136+
gh release delete "${RELEASE_TAG}" --yes --cleanup-tag 2>/dev/null || true
137+
}
138+
trap cleanup ERR
139+
140+
PRERELEASE_FLAG=""
141+
if [[ "${PRERELEASE}" == "true" ]]; then
142+
PRERELEASE_FLAG="--prerelease"
143+
fi
144+
145+
# Create as draft first — draft releases are never immutable, so assets
146+
# can be freely attached. The release becomes immutable only after --draft=false.
147+
gh release create "${RELEASE_TAG}" \
148+
--draft \
149+
--title "${RELEASE_TAG}" \
150+
--generate-notes \
151+
${PRERELEASE_FLAG} \
152+
./artifacts/nuget/*.nupkg \
180153
./artifacts/nuget/*.snupkg
181154
155+
# Publish: marks as latest and becomes immutable. Any retry will clean up above.
156+
gh release edit "${RELEASE_TAG}" \
157+
--draft=false \
158+
--latest
159+
160+
echo "✅ Release ${RELEASE_TAG} published successfully."
161+
182162
- name: Skip release publish
183-
if: ${{ steps.release-trigger.outputs.should_release != 'true' }}
184-
run: echo "package.json did not change on this push, so release publishing was skipped."
163+
if: ${{ steps.release-check.outputs.should_release != 'true' }}
164+
run: echo "Release ${{ steps.version.outputs.tag }} already exists — skipping."
165+

.github/workflows/ci.yml

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
run: dotnet build ${{ env.SOLUTION }} --no-restore --configuration ${{ env.CONFIGURATION }}
5353

5454
- name: Run tests
55-
run: dotnet test --solution ${{ env.SOLUTION }} --no-build --verbosity normal --configuration ${{ env.CONFIGURATION }}
55+
run: dotnet test ${{ env.SOLUTION }} --no-build --verbosity normal --configuration ${{ env.CONFIGURATION }}
5656

5757
build-and-test-samples:
5858
name: Build and Test Samples
@@ -78,7 +78,51 @@ jobs:
7878
run: dotnet build ${{ env.SOLUTION }} --no-restore --configuration ${{ env.CONFIGURATION }}
7979

8080
- name: Run tests
81-
run: dotnet test --solution ${{ env.SOLUTION }} --no-build --verbosity normal --configuration ${{ env.CONFIGURATION }}
81+
run: dotnet test ${{ env.SOLUTION }} --no-build --verbosity normal --configuration ${{ env.CONFIGURATION }}
82+
83+
changeset-check:
84+
name: Changeset Check
85+
runs-on: ubuntu-latest
86+
87+
steps:
88+
- name: Checkout code
89+
uses: actions/checkout@v6
90+
with:
91+
fetch-depth: 0
92+
93+
- name: Check for changeset
94+
env:
95+
HEAD_REF: ${{ github.head_ref }}
96+
PR_LABELS: ${{ toJson(github.event.pull_request.labels.*.name) }}
97+
shell: bash
98+
run: |
99+
set -euo pipefail
100+
101+
# Version Packages PRs are created by the release bot — no changeset needed
102+
if [[ "${HEAD_REF}" == changeset-release/* ]]; then
103+
echo "Version Packages PR — changeset check skipped."
104+
exit 0
105+
fi
106+
107+
# PRs labelled skip-changeset are explicitly opted out (docs-only, CI-only, etc.)
108+
if echo "${PR_LABELS}" | grep -q '"skip-changeset"'; then
109+
echo "skip-changeset label present — changeset check skipped."
110+
exit 0
111+
fi
112+
113+
git fetch origin main --depth=1
114+
115+
changed_files="$(git diff --name-only origin/main...HEAD)"
116+
changeset_files="$(echo "${changed_files}" | grep -E '^\.changeset/[^/]+\.md$' | grep -v 'README\.md' || true)"
117+
118+
if [[ -z "${changeset_files}" ]]; then
119+
echo "::error::No changeset file found."
120+
echo "::error::Run 'just changeset' to create one, or add the 'skip-changeset' label if this PR needs no release note."
121+
exit 1
122+
fi
123+
124+
echo "✅ Changeset found:"
125+
echo "${changeset_files}"
82126
83127
ci-gate:
84128
name: CI Gate
@@ -88,13 +132,15 @@ jobs:
88132
- format-check
89133
- build-and-test
90134
- build-and-test-samples
135+
- changeset-check
91136

92137
steps:
93138
- name: Verify upstream jobs succeeded
94139
env:
95140
FORMAT_CHECK_RESULT: ${{ needs['format-check'].result }}
96141
BUILD_AND_TEST_RESULT: ${{ needs['build-and-test'].result }}
97142
BUILD_AND_TEST_SAMPLES_RESULT: ${{ needs['build-and-test-samples'].result }}
143+
CHANGESET_CHECK_RESULT: ${{ needs['changeset-check'].result }}
98144
shell: bash
99145
run: |
100146
set -euo pipefail
@@ -103,6 +149,7 @@ jobs:
103149
["Format Check"]="${FORMAT_CHECK_RESULT}"
104150
["Build and Test"]="${BUILD_AND_TEST_RESULT}"
105151
["Build and Test Samples"]="${BUILD_AND_TEST_SAMPLES_RESULT}"
152+
["Changeset Check"]="${CHANGESET_CHECK_RESULT}"
106153
)
107154
108155
failures=0

.github/workflows/release-pr.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Release PR
2+
3+
permissions:
4+
contents: write
5+
pull-requests: write
6+
7+
on:
8+
push:
9+
branches:
10+
- main
11+
12+
jobs:
13+
release-pr:
14+
name: Create or update Release PR
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Generate GitHub App token
19+
id: app-token
20+
if: ${{ secrets.APP_ID != '' }}
21+
uses: actions/create-github-app-token@v1
22+
with:
23+
app-id: ${{ secrets.APP_ID }}
24+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
25+
26+
- name: Checkout code
27+
uses: actions/checkout@v6
28+
with:
29+
fetch-depth: 0
30+
token: ${{ steps.app-token.outputs.token || secrets.CHANGESET_TOKEN }}
31+
32+
- name: Set up Bun
33+
uses: oven-sh/setup-bun@v2
34+
35+
- name: Install dependencies
36+
run: bun install
37+
38+
- name: Create or update Release PR
39+
uses: changesets/action@v1
40+
with:
41+
version: bun run version-packages
42+
createGithubReleases: false
43+
env:
44+
GITHUB_TOKEN: ${{ steps.app-token.outputs.token || secrets.CHANGESET_TOKEN }}

.wiki

Submodule .wiki updated from c6b1177 to 39c51bb

0 commit comments

Comments
 (0)