Skip to content

Commit 3873f9b

Browse files
authored
Update templates and JsonCLI docs (#2975)
1 parent 63f07d1 commit 3873f9b

File tree

4 files changed

+69
-88
lines changed

4 files changed

+69
-88
lines changed

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ dist
6969
stats.json
7070

7171
# debugging artifacts
72-
resources/dotnetTemplates
72+
resources/backupTemplates/dotnet/**/cache/
7373

7474
# macOS related extra files
7575
.DS_Store

src/templates/README.md

+38-48
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,37 @@
11
# Azure Function Templates
22

3-
The code in this folder is used to parse and model the [function templates](https://github.com/Azure/azure-webjobs-sdk-templates) provided by the [Azure Functions CLI Feed](https://aka.ms/V00v5v). The Functions CLI Feed provides a central location to get the latest version of all templates used for functions. Currently, this repo leverages the following templates:
3+
The code in this folder is used to parse and model the [function templates](https://github.com/Azure/azure-webjobs-sdk-templates) provided by the [Azure Functions CLI Feed](https://aka.ms/AAbbk68). The Functions CLI Feed provides a central location to get the latest version of all templates used for functions.
44

5-
* [Script Templates](#script-templates) (i.e. JavaScript, C#Script, and Python)
6-
* [.NET Templates](#.net-templates) (i.e. C#)
5+
## Template Sources
6+
7+
Templates are retrieved from the following sources, in order:
8+
1. VS Code extension cache, if the cached version matches the latest version from the CLI Feed
9+
1. Latest templates from the CLI Feed
10+
1. VS Code extension cache, if we fail to get the latest templates or it times out
11+
1. Backup templates stored in `resources/backupTemplates`, if we fail to get the latest templates and the cache is empty
12+
13+
Unit test run separately against all of these template sources (cache, latest, backup) in addition to "staging", which is the pre-production version of "latest". Different template sources can be tested manually with the "azureFunctions.templateSource" setting.
14+
15+
### Updating Backup Templates
16+
17+
Backup templates should be updated every time there is a major change in the latest templates, and otherwise periodically with the release of the extension. In order to update:
18+
1. Modify `AZFUNC_UPDATE_BACKUP_TEMPLATES` to `1` in `.vscode/launch.json`
19+
1. Select "Launch Tests" as the debug configuration
20+
1. F5 the extension
21+
1. Commit changes
22+
23+
> NOTE: This tool was written as a "test" so that it can run in the context of VS Code and our extension. This allows the "backup template" code to be much more tightly integrated with the core templates code, as opposed to something like a gulp task which would have to be completely separate.
724
825
## Script Templates
926

10-
Script templates are retrieved from the 'templateApiZip' property in the CLI Feed. The zip contains data in three parts: templates.json, bindingconfig.json, and resources.json. See below for an example of the schema for the TimerTrigger template:
27+
Basic script templates (i.e. http and timer) are retrieved from the 'templates' property in each entry of the [CLI Feed](https://aka.ms/AAbbk68). More advanced templates (i.e. blob and cosmos) are retrieved from another feed specific to the extension bundle for that project. For example, the default bundle is 'Microsoft.Azure.Functions.ExtensionBundle' and the matching feed is https://functionscdn.azureedge.net/public/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle/index-v2.json
28+
29+
> NOTE: Both template feeds support 'staging' environments for us to test against before moving to production. The main CLI Feed uses a "vX-prerelease" tag, while the bundle feed has a completely different url leveraging "functionscdnstaging" instead of "functionscdn".
30+
31+
In both cases, the templates are split into three parts: templates.json, bindings.json, and resources.json. See below for an example of the schema for the TimerTrigger template:
1132

12-
### Templates.json
33+
<details>
34+
<summary>templates.json</summary>
1335

1436
```json
1537
[
@@ -50,7 +72,10 @@ Script templates are retrieved from the 'templateApiZip' property in the CLI Fee
5072
]
5173
```
5274

53-
### BindingConfig.json
75+
</details>
76+
77+
<details>
78+
<summary>bindings.json</summary>
5479

5580
```json
5681
{
@@ -101,7 +126,10 @@ Script templates are retrieved from the 'templateApiZip' property in the CLI Fee
101126
}
102127
```
103128

104-
### Resources.json
129+
</details>
130+
131+
<details>
132+
<summary>resources.json</summary>
105133

106134
```json
107135
{
@@ -121,46 +149,8 @@ Script templates are retrieved from the 'templateApiZip' property in the CLI Fee
121149
}
122150
```
123151

124-
## .NET Templates
125-
126-
.NET templates are retrieved from the 'itemTemplates' and 'projectTemplates' properties in the CLI Feed. These properties reference two nuget packages. We then leverage the 'Microsoft.TemplateEngine.JsonCli' dll which provides a JSON-based way to interact with .NET templates.
152+
</details>
127153

128-
The following is an example command used to list templates:
129-
130-
```
131-
dotnet <path to extension>/resources/dotnetJsonCli/Microsoft.TemplateEngine.JsonCli.dll --require <path to extension>/resources/dotnetTemplates/itemTemplates-~1.nupkg --require <path to extension>/resources/dotnetTemplates/projectTemplates-~1.nupkg --operation list
132-
```
133-
134-
Example format for the Timer Trigger:
135-
136-
```json
137-
{
138-
"Author": "Microsoft",
139-
"Classifications": [
140-
"Azure Function"
141-
],
142-
"DefaultName": "TimerTriggerCSharp",
143-
"Identity": "Azure.Function.CSharp.TimerTrigger.1.x",
144-
"GroupIdentity": "Azure.Function.TimerTrigger",
145-
"Name": "TimerTrigger",
146-
"ShortName": "Timer",
147-
"Parameters": [
148-
{
149-
"Documentation": "Enter a cron expression of the format '{second} {minute} {hour} {day} {month} {day of week}' to specify the schedule.",
150-
"Name": "Schedule",
151-
"Priority": 0,
152-
"Type": null,
153-
"IsName": false,
154-
"DefaultValue": "0 */5 * * * *",
155-
"DataType": null,
156-
"Choices": null
157-
}
158-
]
159-
}
160-
```
161-
162-
And the following is an example command for creating a template:
154+
## .NET Templates
163155

164-
```
165-
dotnet <path to extension>/resources/dotnetJsonCli/Microsoft.TemplateEngine.JsonCli.dll --require <path to extension>/resources/dotnetTemplates/itemTemplates-~2.nupkg --require <path to extension>/resources/dotnetTemplates/projectTemplates-~2.nupkg --operation create --identity Azure.Function.CSharp.TimerTrigger.2.x --arg:Schedule 0 */5 * * * * --arg:name TimerTriggerCSharp --arg:namespace Company.Function
166-
```
156+
.NET templates are retrieved from the 'itemTemplates' and 'projectTemplates' properties in the CLI Feed. A single version of the Azure Functions runtime might support multiple versions of the .NET runtime, so we use the target framework and sdk from a user's `*.csproj` file to pick the matching templates. We then leverage the JsonCLI tool ('Microsoft.TemplateEngine.JsonCli') which provides a JSON-based way to interact with .NET templates. More information on that tool can be found in the [tools/JsonCli](https://github.com/microsoft/vscode-azurefunctions/tree/main/tools/JsonCli) folder at the root of this repo.

tools/JsonCli/.vscode/launch.json

+21-27
Original file line numberDiff line numberDiff line change
@@ -2,67 +2,61 @@
22
"version": "0.2.0",
33
"configurations": [
44
{
5-
"name": ".NET Core Launch (create function)",
5+
"name": ".NET Core Launch (list templates)",
66
"type": "coreclr",
77
"request": "launch",
88
"preLaunchTask": "build",
99
"program": "${workspaceFolder}/src/bin/Debug/netcoreapp3.0/Microsoft.TemplateEngine.JsonCli.dll",
1010
"args": [
11-
"--require",
12-
"${workspaceFolder}/../../resources/backupTemplates/dotnet/~3/projectTemplates-~3.nupkg",
13-
"--require",
14-
"${workspaceFolder}/../../resources/backupTemplates/dotnet/~3/itemTemplates-~3.nupkg",
11+
"--templateDir",
12+
"${workspaceFolder}/../../resources/backupTemplates/dotnet/~3/netcoreapp3.1/",
1513
"--operation",
16-
"create",
17-
"--identity",
18-
"Azure.Function.CSharp.HttpTrigger.2.x",
19-
"--arg:name HttpTriggerCSharp2",
20-
"--arg:namespace Company.Function",
21-
"--arg:AccessRights \"Anonymous\""
14+
"list"
2215
],
2316
"cwd": "${workspaceFolder}",
2417
"console": "internalConsole",
2518
"stopAtEntry": false,
2619
"internalConsoleOptions": "openOnSessionStart"
2720
},
2821
{
29-
"name": ".NET Core Launch (create project)",
22+
"name": ".NET Core Launch (create function)",
3023
"type": "coreclr",
3124
"request": "launch",
3225
"preLaunchTask": "build",
3326
"program": "${workspaceFolder}/src/bin/Debug/netcoreapp3.0/Microsoft.TemplateEngine.JsonCli.dll",
3427
"args": [
35-
"--require",
36-
"${workspaceFolder}/../../resources/backupTemplates/dotnet/~3/projectTemplates-~3.nupkg",
37-
"--require",
38-
"${workspaceFolder}/../../resources/backupTemplates/dotnet/~3/itemTemplates-~3.nupkg",
28+
"--templateDir",
29+
"${workspaceFolder}/../../resources/backupTemplates/dotnet/~3/netcoreapp3.1/",
3930
"--operation",
4031
"create",
4132
"--identity",
42-
"Microsoft.AzureFunctions.ProjectTemplate.CSharp.3.x",
43-
"--arg:name",
44-
"testProj",
45-
"--arg:AzureFunctionsVersion",
46-
"v3"
33+
"Azure.Function.CSharp.HttpTrigger.2.x",
34+
"--arg:name HttpTriggerCSharp2",
35+
"--arg:namespace Company.Function",
36+
"--arg:AccessRights \"Anonymous\""
4737
],
4838
"cwd": "${workspaceFolder}",
4939
"console": "internalConsole",
5040
"stopAtEntry": false,
5141
"internalConsoleOptions": "openOnSessionStart"
5242
},
5343
{
54-
"name": ".NET Core Launch (list templates)",
44+
"name": ".NET Core Launch (create project)",
5545
"type": "coreclr",
5646
"request": "launch",
5747
"preLaunchTask": "build",
5848
"program": "${workspaceFolder}/src/bin/Debug/netcoreapp3.0/Microsoft.TemplateEngine.JsonCli.dll",
5949
"args": [
60-
"--require",
61-
"${workspaceFolder}/../../resources/backupTemplates/dotnet/~3/projectTemplates-~3.nupkg",
62-
"--require",
63-
"${workspaceFolder}/../../resources/backupTemplates/dotnet/~3/itemTemplates-~3.nupkg",
50+
"--templateDir",
51+
"${workspaceFolder}/../../resources/backupTemplates/dotnet/~3/netcoreapp3.1/",
6452
"--operation",
65-
"list"
53+
"create",
54+
"--identity",
55+
"Microsoft.AzureFunctions.ProjectTemplate.CSharp.3.x",
56+
"--arg:name",
57+
"testProj",
58+
"--arg:AzureFunctionsVersion",
59+
"v3"
6660
],
6761
"cwd": "${workspaceFolder}",
6862
"console": "internalConsole",

tools/JsonCli/README.md

+9-12
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@
44

55
This tool is leveraged by the Functions extension at the root of this repo. It provides a JSON-based way to interact with .NET Templates. It also allows us to use templates directly from a nuget package, rather than forcing the user to install the templates machine-wide.
66

7+
> NOTE: This tool assumes the user already has the .NET CLI installed on their machine, but that means we have to ship multiple target frameworks with the extension to work with whatever they have installed. One alternative would be to leverage the [.NET Install Tool](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.vscode-dotnet-runtime) to install a specific version of .NET and then the extension would only need to ship that target framework.
8+
79
## Prerequisites
810

9-
[.NET CLI](https://docs.microsoft.com/dotnet/core/tools/?tabs=netcore2x)
11+
[.NET CLI](https://docs.microsoft.com/dotnet/core/tools/)
1012

1113
## Example Usage
1214

1315
### List
1416

1517
```bash
16-
dotnet --require ./projectTemplates-~2.nupkg --require ./itemTemplates-~2.nupkg --operation list
18+
dotnet --templateDir ./../../resources/backupTemplates/dotnet/~3/netcoreapp3.1/ --operation list
1719
```
1820

19-
This will list all templates included in the NuGet packages specified with the `require` parameter. Multiple packages can be specified in the format of a disk path, a NuGet package ID, or a NuGet package ID and version formatted as `{id}::{version}`. Example output:
21+
This will list all templates based on the `templateDir` parameter. The template directory should have an "item.nupkg" for item templates and a "project.nupkg" for project templates. Example output:
2022

2123
```json
2224
[
@@ -49,10 +51,10 @@ This will list all templates included in the NuGet packages specified with the `
4951
### Create
5052

5153
```bash
52-
dotnet --require projectTemplates-~2.nupkg --require itemTemplates-~2.nupkg --operation create --identity Azure.Function.CSharp.TimerTrigger.1.x --arg:name TimerTriggerCSharp1 --arg:namespace Company.Function --arg:Schedule "0 */5 * * * *"
54+
dotnet --templateDir ./../../resources/backupTemplates/dotnet/~3/netcoreapp3.1/ --operation create --identity Azure.Function.CSharp.TimerTrigger.1.x --arg:name TimerTriggerCSharp1 --arg:namespace Company.Function --arg:Schedule "0 */5 * * * *"
5355
```
5456

55-
This will create the template with the specified identity. The `require` parameter is the same as used above. The `identity` and `arg` parameters can be retrieved from the result of a list operation, shown above. The `name` and `namespace` args apply to all templates.
57+
This will create the template with the specified identity. The `templateDir` parameter is the same as used above. The `identity` and `arg` parameters can be retrieved from the result of a list operation, shown above. The `name` and `namespace` args apply to all templates.
5658

5759
## Contributing
5860

@@ -61,14 +63,9 @@ In order to work on this tool, make sure to install the [VS Code Debugger for C#
6163
### Debug
6264

6365
1. When prompted, make sure to restore NuGet packages
64-
1. Ensure the latest .NET templates are downloaded. The easiest way is to F5 the extension at the root of this repo and open the Functions explorer to make sure the extension is activated. This will automatically download the latest NuGet packages to `resources/dotnetTemplates/`.
65-
1. From the debug window, select either the 'create template' or 'list templates' option based on what you want to test
66+
1. From the debug window, select either the 'create function', 'create project', or 'list templates' option based on what you want to test
6667
1. Start debugging!
6768

6869
### Publish
6970

70-
In order to update the dll's shipped with the extension, you need to run a 'publish':
71-
72-
1. Select 'Run Task' from the command palette
73-
1. Select 'publish'
74-
1. Commit changes
71+
In order to update the dll's shipped with the extension, you need to [run a build](https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_build?definitionId=13600) with `SignType` set to `Real` and download those bits into the `resources/dotnetJsonCli` folder as appropriate.

0 commit comments

Comments
 (0)