Skip to content

Commit 0e33270

Browse files
committed
Merge remote-tracking branch 'origin/release/3.6.0'
2 parents 2c4aadf + ffd4327 commit 0e33270

3 files changed

Lines changed: 185 additions & 2 deletions

File tree

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Copilot Playbook: Elsa Core Release Notes (GitHub Release + PR/commit links)
2+
3+
## Goal
4+
Generate consistent GitHub Release notes for `elsa-workflows/elsa-core` between two tags/refs, including:
5+
- a short **Highlights** section up top
6+
- standard grouped sections (Breaking/Features/Improvements/Fixes/Tests/CI)
7+
- **GitHub-style** PR/commit references at the end of bullets: `(#1234)` or `(abcd123)`
8+
- a short **Full changelog** section (one line per commit/PR)
9+
- optional **Known issues** section when applicable
10+
11+
## Inputs to provide (required)
12+
- Repository: `elsa-workflows/elsa-core`
13+
- From tag/ref: `<FROM>`
14+
- To tag/ref: `<TO>`
15+
16+
Also provide ONE of:
17+
- `git log --oneline <FROM>..<TO>` output (preferred), OR
18+
- compare URL: `https://github.com/elsa-workflows/elsa-core/compare/<FROM>...<TO>`
19+
20+
Optionally provide:
21+
- whether merges are squash (often include `(#NNNN)` in subject) vs merge commits
22+
- any release-specific callouts you want forced into Highlights / Known issues
23+
24+
## Output format (required)
25+
- Return a single Markdown file using a four-backtick fenced block:
26+
- filename: `release-notes-<TO>.md` (or `release-notes-<version>.md`)
27+
- Use this section order and headings exactly:
28+
29+
1. Title and compare range
30+
2. `### 🌟 Highlights`
31+
3. `### ⚠️ Breaking changes / upgrade notes`
32+
4. `### ✨ New features`
33+
5. `### 🔧 Improvements`
34+
6. `### 🐛 Fixes`
35+
7. `### 🧩 Developer-facing changes` (omit if none)
36+
8. `### 🧪 Tests` (omit if none)
37+
9. `### 🔁 CI / Build` (omit if none)
38+
10. `### 🧭 Known issues` (omit if none provided/known)
39+
11. `### 📦 Full changelog (short)`
40+
41+
## Link style rules
42+
- Prefer PR number if available: end bullet with `(#NNNN)`
43+
- If no PR association: end bullet with `(abcd123)` short SHA (7–12 chars)
44+
- If multiple relevant PRs/commits: include multiple suffixes, e.g. `(#7172) (abcd123)`
45+
46+
Never invent PR numbers. Only use what is present in commit subjects, merge commits, or explicitly provided.
47+
48+
## PR title vs commit subject convention (new)
49+
- If a PR number is available, prefer **PR title wording** over commit subject wording **when you have the PR title**.
50+
- If PR titles are not available (e.g., only `git log` output), use commit subjects as-is.
51+
- If you *do* have PR titles and they differ significantly from commit subjects:
52+
- use the PR title in the release note bullet
53+
- keep “Full changelog (short)” as the raw commit subjects (or PR titles if you have them consistently)
54+
55+
(If you want PR-title-first release notes, provide a list of PR URLs/titles or enable an API-derived PR list in the session.)
56+
57+
## Highlights convention (new)
58+
- 3–6 bullets max
59+
- Must be user-facing and high-signal:
60+
- new capabilities
61+
- resilience / reliability improvements
62+
- important defaults/behavior changes
63+
- Each highlight bullet should still end with `(#NNNN)` / `(sha)`.
64+
65+
## Known issues convention (new)
66+
Only include if the user provides known issues or you can clearly infer them from the provided material (avoid guessing).
67+
Each entry should include:
68+
- symptom (what breaks)
69+
- workaround (if known)
70+
- reference suffix `(#NNNN)` / `(sha)` if applicable
71+
72+
If none are provided, omit the section entirely.
73+
74+
## How to build the content (process)
75+
1. Parse the provided commit list into an ordered changelog.
76+
2. Extract PR numbers from subjects:
77+
- `(#7174)` at end of subject
78+
- `Merge pull request #7157 ...`
79+
3. Group changes into sections:
80+
- Breaking: API changes, package swaps, SDK/toolchain, serialization model changes
81+
- Features: new APIs/modules/capabilities
82+
- Improvements: performance, resilience, refactors that improve behavior
83+
- Fixes: correctness, bugs
84+
- Developer-facing: attributes, extension points, new hooks/contracts
85+
- Tests: new test projects, new coverage, determinism fixes
86+
- CI/Build: workflow changes, branch triggers, packaging/versioning
87+
4. Produce concise bullets:
88+
- Start with an action verb (“Added”, “Introduced”, “Fixed”, “Improved”, “Updated”, “Removed”)
89+
- One idea per bullet
90+
- Add details as sub-bullets only when necessary (max 2 levels)
91+
- Append PR/commit suffix at end
92+
5. Generate **Highlights** by selecting the top 3–6 bullets across all sections (no duplicates).
93+
6. Add **Full changelog (short)**:
94+
- include every commit line from the provided input range, in the same order
95+
- each line should include PR number if present; otherwise SHA
96+
97+
## Consistency checks before finalizing
98+
- Compare range line present: `Compare: <FROM>...<TO>`
99+
- Highlights present (3–6 bullets)
100+
- Every bullet has suffix `(#NNNN)` or `(sha)` where available
101+
- No PR numbers are guessed
102+
- Full changelog includes all commits provided
103+
- Optional sections (Developer-facing / Tests / CI / Known issues) are omitted if empty
104+
105+
## Example prompt for a new session
106+
“Generate GitHub Release notes for `elsa-workflows/elsa-core` from `<FROM>` to `<TO>`. Use the template with **Highlights** and **Known issues** (only if I provide them). Prefer PR titles when available, otherwise use commit subjects. Use GitHub-style `(#NNNN)` references and include a short Full changelog. Here is `git log --oneline <FROM>..<TO>`: …”

.github/workflows/packages.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ jobs:
101101
path: artifacts/coverage
102102

103103
- name: Upload Pages artifact
104-
if: always() && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop/3.6.0')
104+
if: always() && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/'))
105105
uses: actions/upload-pages-artifact@v3
106106
with:
107107
path: './artifacts/coverage-report'
@@ -138,7 +138,7 @@ jobs:
138138
run: |
139139
if [[ "${{ github.ref }}" == refs/tags/* && "${{ github.event_name }}" == "release" && ("${{ github.event.action }}" == "published" || "${{ github.event.action }}" == "prereleased") ]]; then
140140
git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
141-
git branch --remote --contains | grep origin/main
141+
git branch --remote --contains | grep -E 'origin/(main|release/)'
142142
else
143143
git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
144144
git branch --remote --contains | grep origin/${BRANCH_NAME}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+

2+
using System.Text.Json;
3+
using System.Text.Json.Serialization;
4+
using Elsa.Workflows.Models;
5+
6+
namespace Elsa.Workflows.Core.UnitTests.Models;
7+
8+
public sealed class JsonActivityConstructorContextHelperTests
9+
{
10+
private static readonly JsonSerializerOptions _serializerOptions = new();
11+
12+
[Theory]
13+
[InlineData("_Metadata")]
14+
[InlineData("Metadata")]
15+
[InlineData("_CustomProperties")]
16+
[InlineData("CustomProperties")]
17+
public void When_InputName_Is_ReservedKeyWord_Then_ThrowsException_WhenReadingInputs(string reservedInputName)
18+
{
19+
// Arrange
20+
var activityDescriptor = new ActivityDescriptor
21+
{
22+
Inputs =
23+
[
24+
new()
25+
{
26+
Name = reservedInputName,
27+
Type = typeof(object),
28+
IsSynthetic = true
29+
}
30+
]
31+
};
32+
var jsonElement = GetJsonElementWithReservedInputName(reservedInputName);
33+
34+
// Act & Assert
35+
Assert.Throws<KeyNotFoundException>(() =>
36+
{
37+
_ = JsonActivityConstructorContextHelper.CreateActivity<WorkflowAsActivity>(
38+
activityDescriptor,
39+
jsonElement,
40+
_serializerOptions
41+
);
42+
});
43+
}
44+
45+
private static JsonElement GetJsonElementWithReservedInputName(string inputName)
46+
{
47+
const string json = "{\"workflowDefinitionId\":\"Id\",\"id\":\"Id\",\"nodeId\":\"NodeId\",\"name\":\"Workflow-as-activity\",\"type\":\"WorkflowAsActivity\",\"customProperties\":{\"canStartWorkflow\":false,\"runAsynchronously\":false},\"metadata\":{\"designer\":{\"position\":{\"x\":1525.99609375,\"y\":171.5625},\"size\":{\"width\":230.4296875,\"height\":68.4375}},\"displayText\":\"Test\"},\"<inputName>\":{\"typeName\":\"Object\",\"expression\":{\"type\":\"JavaScript\",\"value\":\"return {\\n \\u0022key\\u0022 : obj.value\\n}\"},\"memoryReference\":{\"id\":\"memref:input--name\"}}}";
48+
var jsonWithInputName = json.Replace("<inputName>", inputName);
49+
return JsonElement.Parse(jsonWithInputName);
50+
}
51+
52+
private class WorkflowAsActivity : IActivity
53+
{
54+
public string Id { get; set; } = "Id";
55+
public string NodeId { get; set; } = "NodeId";
56+
public string? Name { get; set; } = "Workflow-as-activity";
57+
public string Type { get; set; } = "WorkflowAsActivity";
58+
public int Version { get; set; } = 1;
59+
60+
[JsonIgnore]
61+
public IDictionary<string, object> CustomProperties { get; set; } = new Dictionary<string, object>();
62+
public IDictionary<string, object> SyntheticProperties { get; set; } = new Dictionary<string, object>();
63+
64+
[JsonIgnore]
65+
public IDictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>();
66+
67+
public ValueTask<bool> CanExecuteAsync(ActivityExecutionContext context)
68+
{
69+
return new(true);
70+
}
71+
72+
public ValueTask ExecuteAsync(ActivityExecutionContext context)
73+
{
74+
return new();
75+
}
76+
}
77+
}

0 commit comments

Comments
 (0)