Skip to content

Commit 6af3eed

Browse files
Copilotascott18
andauthored
Generate comprehensive GitHub Copilot instructions for Coalesce repository (#583)
--------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: ascott18 <[email protected]> Co-authored-by: Andrew Scott <[email protected]>
1 parent d1ae43a commit 6af3eed

File tree

8 files changed

+140
-34
lines changed

8 files changed

+140
-34
lines changed

.github/copilot-instructions.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Coalesce Framework Development Instructions
2+
3+
Always follow these instructions first and fallback to additional search and context gathering only when the information here is incomplete or found to be in error.
4+
5+
## Project Overview
6+
7+
Coalesce is a framework for rapid development of ASP.NET Core + Vue.js web applications. It generates DTOs, API controllers, and TypeScript from Entity Framework Core models and other C# code.
8+
9+
## Prerequisites & Dependencies
10+
11+
The required tools and dependencies are automatically installed via the GitHub Actions workflow at `.github/workflows/copilot-setup-steps.yml`.
12+
13+
## Instructions
14+
15+
- Format PR titles with Semantic Commits. The work item number should follow the colon after the commit type like `feat: #12345 added ...`
16+
- Always update the documentation when making changes or adding features that will affect developers who use Coalesce.
17+
- Always add an entry to CHANGELOG.md when adding new features or fixing non-trivial bugs.
18+
- Avoid making breaking changes if not necessary. A less obvious example of a breaking change would be changing an existing CSS class name.
19+
- Consider adding or updating example files in `playground\Coalesce.Web.Vue3\src\examples` when making changes to coalesce-vue-vuetify.
20+
21+
## Validation Checklist
22+
23+
After making changes, ALWAYS run this validation sequence:
24+
25+
1. **Build verification**:
26+
From the repo root:
27+
28+
```bash
29+
npm ci
30+
dotnet build
31+
cd src/coalesce-vue && npm run build
32+
cd ../coalesce-vue-vuetify3 && npm run build
33+
```
34+
35+
2. **Test verification**:
36+
From the repo root:
37+
38+
```bash
39+
dotnet test
40+
cd src/coalesce-vue && npm run test
41+
cd ../coalesce-vue-vuetify3 && npm run test
42+
```
43+
44+
3. **Template verification**:
45+
If you make changes to the template in the `templates` directory, validate the changes by running `TestLocal.ps1 -- "--FeatureOne --FeatureTwo"` where the FeatureOne, FeatureTwo parameters are replaced with each flag that might affect the changes you made. Run it multiple times if there are different combinations of feature flags that might interact in different ways. The flags are the variables checked by the `#if` in the template code.
46+
47+
4. **Documentation verification**:
48+
If the documentation was updated, run `npm run build` in the docs folder. You can expect the link checks to fail - you do not have access to the internet to validate the links.
49+
50+
REMEMBER: NEVER CANCEL long-running build operations.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: "Copilot Setup Steps"
2+
3+
# Automatically run the setup steps when they are changed to allow for easy validation, and
4+
# allow manual testing through the repository's "Actions" tab
5+
on:
6+
workflow_dispatch:
7+
push:
8+
paths:
9+
- .github/workflows/copilot-setup-steps.yml
10+
pull_request:
11+
paths:
12+
- .github/workflows/copilot-setup-steps.yml
13+
14+
jobs:
15+
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
16+
copilot-setup-steps:
17+
runs-on: ubuntu-latest
18+
19+
# Set the permissions to the lowest permissions possible needed for your steps.
20+
# Copilot will be given its own token for its operations.
21+
permissions:
22+
contents: read
23+
24+
timeout-minutes: 30
25+
26+
steps:
27+
- name: Checkout code
28+
uses: actions/checkout@v4
29+
30+
- name: Setup dotnet
31+
uses: actions/setup-dotnet@v4
32+
with:
33+
dotnet-version: |
34+
8.0.x
35+
9.0.x
36+
37+
- name: Install JavaScript dependencies
38+
run: npm ci
39+
40+
- name: Restore .NET packages
41+
run: dotnet restore
42+
43+
- name: Build solution
44+
run: dotnet build --no-restore --configuration Release
45+
46+
- name: Build coalesce-vue-vuetify3
47+
working-directory: src/coalesce-vue-vuetify3
48+
run: |
49+
npm run build-local-deps
50+
npm run build

.github/workflows/part-build.yml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,14 +139,38 @@ jobs:
139139
- run: npm ci
140140
working-directory: ${{ github.workspace }}
141141

142-
- run: npm run build
142+
- name: Build docs (without linkcheck)
143+
run: npm run build-only
143144

144145
- name: Upload Artifact
145146
uses: actions/upload-artifact@v4
146147
with:
147148
name: docs
148149
path: docs/.vitepress/dist/Coalesce
149150

151+
linkcheck-docs:
152+
runs-on: ubuntu-latest
153+
needs: build-docs
154+
defaults:
155+
run:
156+
shell: bash
157+
working-directory: docs
158+
159+
steps:
160+
- uses: actions/checkout@v4
161+
162+
- run: npm ci
163+
# working-directory: ${{ github.workspace }}
164+
165+
- name: Download built docs
166+
uses: actions/download-artifact@v4
167+
with:
168+
name: docs
169+
path: docs/.vitepress/dist/Coalesce
170+
171+
- name: Run linkcheck
172+
run: npm run linkcheck
173+
150174
validate-template:
151175
runs-on: ubuntu-latest
152176
name: "test template: ${{matrix.testCase}}"

docs/check-links.mjs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ let server;
2323
try {
2424
// Start static file server
2525
server = createServer((req, res) =>
26-
handler(req, res, { public: ".vitepress/dist" })
26+
handler(req, res, { public: ".vitepress/dist" }),
2727
);
2828

2929
await new Promise((resolve) => server.listen(8087, resolve));
@@ -32,7 +32,12 @@ try {
3232
await waitOn({ resources: ["http://localhost:8087"], timeout: 30000 });
3333

3434
// Run linkcheck
35-
await run("npm", ["run", "linkcheck"]);
35+
await run("linkcheck", [
36+
"localhost:8087/Coalesce",
37+
"-e",
38+
"--skip-file",
39+
"./.vitepress/linkcheck-skip-file.txt",
40+
]);
3641

3742
process.exit(0);
3843
} catch (err) {

docs/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
"license": "Apache-2.0",
99
"scripts": {
1010
"dev": "vitepress dev",
11-
"linkcheck": "linkcheck localhost:8087/Coalesce -e --skip-file ./.vitepress/linkcheck-skip-file.txt",
12-
"build": "cspell \"**/*.md\" && vitepress build --outDir .vitepress/dist/Coalesce && node check-links.mjs"
11+
"build-only": "cspell \"**/*.md\" && vitepress build --outDir .vitepress/dist/Coalesce",
12+
"linkcheck": "node check-links.mjs",
13+
"build": "npm run build-only && npm run linkcheck"
1314
},
1415
"dependencies": {
1516
"shiki": "1.4.0"

src/IntelliTect.Coalesce.CodeGeneration.Api/Generators/ModelApiController.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,9 @@ private static void WriteEtagProcessing(CSharpCodeBuilder b, MethodViewModel met
260260
// in the querystring this means the client has prior knowledge
261261
// about the current version via the VaryByProperty's value).
262262

263-
var clientCacheDurationSeconds = method.GetAttribute<ExecuteAttribute>().GetValue(a => a.ClientCacheDurationSeconds);
263+
var clientCacheDurationSeconds = method
264+
.GetAttribute<ExecuteAttribute>()
265+
?.GetValue(a => a.ClientCacheDurationSeconds);
264266
if (clientCacheDurationSeconds != null)
265267
{
266268
b.Line($"_cacheControlHeader.MaxAge = TimeSpan.FromSeconds({clientCacheDurationSeconds.Value});");

src/IntelliTect.Coalesce/DataAnnotations/ExecuteAttribute.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,12 @@ public bool ValidateAttributes
7676
/// Defaults to 30 days (2,592,000 seconds) if not specified.
7777
/// </para>
7878
/// </summary>
79-
public int? ClientCacheDurationSeconds { get; set; }
79+
public int ClientCacheDurationSeconds { get; set; }
8080

8181
/// <summary>
8282
/// Gets the ClientCacheDuration as a TimeSpan based on ClientCacheDurationSeconds.
8383
/// </summary>
84-
public TimeSpan? ClientCacheDuration => ClientCacheDurationSeconds.HasValue
85-
? TimeSpan.FromSeconds(ClientCacheDurationSeconds.Value)
86-
: null;
84+
public TimeSpan? ClientCacheDuration => TimeSpan.FromSeconds(ClientCacheDurationSeconds);
8785
}
8886

8987
public enum HttpMethod

src/IntelliTect.Coalesce/TypeDefinition/Helpers/AttributeViewModel.cs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,29 +62,5 @@ protected AttributeViewModel(ReflectionRepository? reflectionRepository)
6262
return GetValue<T>(propertyExpression.GetExpressedProperty().Name);
6363
}
6464

65-
public T? GetValue<T>(
66-
Expression<Func<TAttribute, Nullable<T>>> propertyExpression,
67-
Expression<Func<TAttribute, bool>>? hasValueExpression = null
68-
)
69-
where T : struct
70-
{
71-
// In reflection contexts, for attributes that can have "unset" as a value that means null,
72-
// we have to check this state with an additional property. E.g. ExecuteAttribute.ValidateAttributes.
73-
// In symbol contexts, the absence of syntax that assigns a value to the property implies this "unset" state.
74-
if (hasValueExpression is not null)
75-
{
76-
// `hasValue` will always be non-null in reflection contexts,
77-
// and always null in symbol contexts where the HasValue property won't ever be set.
78-
var hasValue = GetValue<bool>(hasValueExpression.GetExpressedProperty().Name);
79-
if (hasValue == false)
80-
{
81-
return null;
82-
}
83-
}
84-
85-
86-
return GetValue<T>(propertyExpression.GetExpressedProperty().Name);
87-
}
88-
8965
public abstract object? GetValue(string valueName);
9066
}

0 commit comments

Comments
 (0)