I'm creating some templates for application types I use often.
It would be cool if it were possible to combine templates.
A concrete example (sorry for the terrible "markdown art")
let's assume I have the following templates:
I would love being able to create templates like
and so on...
It would be up to the root "template" to fetch and dispatch all needed parameters to the "sub" templates
Currently there is no support for taking multiple existing templates and using them in another "multi-template" template...
If I understand correctly you want to have easy way to create new template where you basically say something like this:
{
"name": "My awesome multi-project template",
"shortName": "grpc-with-webapi-and-tests",
"subtemplates": [
{
"shortname": "web-api-app",
"outputFolder": "web-api/src/web-api-app/"
},
{
"shortname": "tests-lib",
"outputFolder": "web-api/tests/tests-lib/"
},
{
"shortname": "grpc-server-app",
"outputFolder": "grpc-server/src/grpc-server-app/"
},
{
"shortname": "tests-lib",
"outputFolder": "grpc-server/tests/tests-lib/"
}
]
}
Of course this would be even more complicated because it needs to create .sln and Directory.Build.props files.. and fill them...
But my question is... How do you propose parameters for this subtemplates to be passed in via CLI arguments? What if some parameters have same name in grpc-server-app template and web-api-app but have different meaning...
hey! thanks for your quick answer.
I can see the difficulties of filling the solution file but otherwise I thought of the root template a proper template with its own content.
As for the parameters, I see two cases:
1) same parameter and same value shared by two sub templates (e.g. target framework, -f, both use net50). In this case the root template can have the same parameter and the sub templates just take it in as-is.
2) same parameter but different values (one app uses net50 and the other uses netcoreapp3.1). In this case, the root project would define two parameters and dispatch each to their own project.
Maybe each sub-template could have an identifier that can be referred to in a "forwardTo" property when defining a symbol?
Building on your sample json...
{
"name": "My awesome multi-project template",
"shortName": "grpc-with-webapi-and-tests",
"subtemplates": [
{
"id": "frontend",
"shortname": "web-api-app",
"outputFolder": "web-api/src/web-api-app/"
},
{
"id": "frontend-tests",
"shortname": "tests-lib",
"outputFolder": "web-api/tests/tests-lib/"
},
{
"id": "backend",
"shortname": "grpc-server-app",
"outputFolder": "grpc-server/src/grpc-server-app/"
},
{
"id": "backend-tests",
"shortname": "tests-lib",
"outputFolder": "grpc-server/tests/tests-lib/"
}
],
"symbols": {
"frontend-targetFramework": {
"choices": ["net50", "netcoreapp31"],
"description": "something something",
"type": "parameter",
"forwardTo": ["frontend"]
},
"backend-targetFramework": {
"choices": ["net50", "netcoreapp31"],
"description": "something something",
"type": "parameter",
"forwardTo": ["backend"]
},
"unitTests-targetFramework": {
"choices": ["net50", "netcoreapp31"],
"description": "something something",
"type": "parameter",
"forwardTo": ["backend-tests", "frontend-tests"]
}
}
}
This will need a lot of effort, we will consider doing...
I can imagine. Thanks for your consideration
This feature would massively reduce the hassle of maintaining broadly-used templates. E.g., if the files in template "a" are needed in templates "b", "c", and "d", I don't want to maintain updates to all four templates. I'd rather just have "a" referenced by the others and not have to copy the same code 4 times.
As a workaround, I make the commonly-used template run as a post-action in other templates:
Here's an example which uses bash or powershell depending on the OS:
"postActions": [
{
"condition": "(OS != \"Windows_NT\")",
"actionId": "3A7C4B45-1F5D-4A30-959A-51B88E82B5D2",
"args": {
"executable": "bash",
"args": "-c \"dotnet new sebtfkeyvault 2>&1 &\"",
"redirectStandardOutput": false
},
"manualInstructions": [
{
"text": "Run 'dotnet new sebtfkeyvault'"
}
],
"continueOnError": true,
"description": "add key vault files"
},
{
"condition": "(OS == \"Windows_NT\")",
"actionId": "3A7C4B45-1F5D-4A30-959A-51B88E82B5D2",
"args": {
"executable": "PowerShell",
"args": "-noprofile -c \"Start-Process -NoNewWindow dotnet -ArgumentList new,sebtfkeyvault\"",
"redirectStandardOutput": false
},
"manualInstructions": [
{
"text": "Run 'dotnet new sebtfkeyvault'"
}
],
"continueOnError": true,
"description": "add key vault files"
}
]
Note that, because the post actions run the templating engine, they need to run in the background (accomplished in bash by ending the command with & and in powershell by using Start-Process ) to prevent the process from hanging. Apparently the templating engine can't run recursively.
Limitations of this workaround are that parameters can't be passed in to the nested templates and errors are invisible in the powershell post actions.
That's an interesting workaround.
That would also allow a dirty fix for the problem of adding projects to the solution file.
Remove-Item "*.sln"
dotnet new sln
Get-ChildItem -Filter "*.csproj" -Recurse | ForEach-Object { dotnet sln add $_.FullName }
I reckon it's a brute force workaround but it works under the assumption that you have a single solution file named like the root directory.
The added benefit of this approach is that dotnet sln add creates solution folders matching the filesystem layout (e.g. src and
tests).
Most helpful comment
This feature would massively reduce the hassle of maintaining broadly-used templates. E.g., if the files in template "a" are needed in templates "b", "c", and "d", I don't want to maintain updates to all four templates. I'd rather just have "a" referenced by the others and not have to copy the same code 4 times.
As a workaround, I make the commonly-used template run as a post-action in other templates:
Here's an example which uses bash or powershell depending on the OS:
Note that, because the post actions run the templating engine, they need to run in the background (accomplished in bash by ending the command with
&and in powershell by usingStart-Process) to prevent the process from hanging. Apparently the templating engine can't run recursively.Limitations of this workaround are that parameters can't be passed in to the nested templates and errors are invisible in the powershell post actions.