Skip to content

{Debug} Teams Toolkit VS Code Tasks

Yiqing Zhao edited this page Nov 14, 2024 · 13 revisions

Teams Toolkit VS Code Tasks

A Teams Toolkit generated project has pre-defined a set of VS Code tasks in its .vscode/tasks.json. These tasks are for debugging and have corresponding arguments as inputs. This page shows the details about how these tasks are defined and how to customize with your own args.

Note: these tasks are generated by Teams Toolkit (>= 4.1.0). To use these tasks in old Teams Toolkit project, see Upgrade section.

Overall Contract

Aligning with the official VS Code schema, the tasks.json contains tasks top-level properties, which defines all the tasks and execution sequence used by Teams Toolkit. Following shows the summary of those pre-defined tasks:

Task Label
                     (Type:Command)                     
Description
Start Teams App Locally The entry task of debug, to be referenced by launch.json.
Validate & Install prerequisites
(teamsfx:debug-check-prerequisites)
Check and auto-resolve prerequisites required by debugging.
Install NPM packages
(teamsfx:debug-npm-install)
NPM install for each sub-project.
Install Azure Functions binding extensions
(shell:dotnet ...)
Install extension for Azure Functions sub-project.
Start local tunnel
(teamsfx:debug-start-local-tunnel)
Start local tunneling for bot sub-project.
Set up tab
(teamsfx:debug-set-up-tab)
Prepare local launch information for Tab.
Set up bot
(teamsfx:debug-set-up-bot)
Register resources and prepare local launch information for Bot.
Set up SSO
(teamsfx:debug-set-up-sso)
Register resources and prepare local launch information for SSO functionality.
Build & Upload Teams manifest
(teamsfx:debug-prepare-manifest)
Build then upload Teams App manifest.
Start services
(shell:npm run ...)
Launch all local services.

Note: Depend on your project type, your tasks.json may contain a subset of above tasks.

For customization, all teamsfx:debug- tasks contain args as inputs. See each section of task definition about the args schema.

Task Definition

This sections shows the details of each task.

Start Teams App Locally

This task is the entry point of all other tasks. It represents the full flow to launch Teams app locally. If you'd like to skip any step(s), just comment it out, e.g.,

{
  "label": "Start Teams App Locally",
  "dependsOn": [
    "Validate & Install prerequisites",
    //// comment out any step(s) you'd like to skip
    // "Install NPM packages",
    "Install Azure Functions binding extensions",
    "Start local tunnel",
    "Set up Tab",
    "Set up Bot",
    "Set up SSO",
    "Build & Upload Teams manifest",
    "Start services"
  ],
  "dependsOrder": "sequence"
}

Validate & Install prerequisites

This task is to validate and install prerequisites that will be used in followed debug steps. If you'd like to skip checking any prerequisite(s), just comment it out.

Arguments type required description
prerequisites array required The enabled prerequisite checkers. Checkers: nodejs, m365Account, devCert, func, ngrok, dotnet, portOccupancy
portOccupancy array required The ports to check if they are in use.
prerequisites description
nodejs Validate if Node.js is installed.
m365Account Sign-in prompt for Microsoft 365 account, then validate if the account enables the sideloading permission.
devCert Install localhost SSL certificate. It's used to serve the development sites over HTTPS to debug the Tab app in Teams.
func Install Azure Functions Core Tools. It's used to serve Azure Functions hosted project locally.
ngrok Install Ngrok. Bot project requires a public message endpoint, and ngrok can help create public tunnel for your local service.
dotnet Ensure .NET Core SDK is installed. TeamsFx Azure Functions project depends on extra .NET binding extensions for HTTP trigger authorization.
portOccupancy Validate available ports to ensure those debug ones are not occupied.

Note: Teams Toolkit downloads npm package ngrok@4.3.3 which contains NGROK v2.3.40. Customer must have a valid license to use NGROK software. Microsoft does not license use of the NGROK.

Sample

{
    "label": "Validate & Install prerequisites",
    "type": "teamsfx",
    "command": "debug-check-prerequisites",
    "args": {
        "prerequisites": [
            "nodejs",
            "m365Account",
            "func",
            //// comment out any checker(s) you'd like to skip
            // "ngrok",
            "portOccupancy"
        ],
        "portOccupancy": [
            53000, // tab service port
            3978, // bot service port
            //// add or update your own port(s) to be validated
            // 9239, // bot debug port
            2233
        ]
    }
},

For newly created project, there may be following ports to be validated:

  • 53000: the default port for local tab service
  • 3978: the default port for local bot service
  • 9239: the default debugger port for local bot service
  • 7071: the default port for local api/backend service
  • 9229: the default debugger port for local api/backend service
  • 4321: the default port for local SPFx service

Install NPM packages

This task is to install npm packages for all sub projects.

Arguments Type Required Description
projects array required The configuration for each subproject.
forceUpdate boolean optional Default: false. false: only install when dependency changes. true: always run npm install script.
projects Type Required Description
npmInstallArgs array optional The args of the npm install command. e.g. ["--no-audit"] means execute the npm install --no-audit command.
cwd string required Target folder.

Sample

{
  "label": "Install NPM packages",
  "type": "teamsfx",
  "command": "debug-npm-install",
  "args": {
    "projects": [
      {
        "cwd": "${workspaceFolder}/tabs",
        "npmInstallArgs": [
          "--no-audit",
          // use your own npm install args
          "--registry=https://my-npm-reg/..."
        ]
      },
      {
        "cwd": "${workspaceFolder}/bot",
        "npmInstallArgs": ["--no-audit"]
      }
    ],
    "forceUpdate": false
  }
}

Install Azure Functions binding extensions

This task is to install TeamsFx Azure Functions binding extensions for your backend API project. It's a VS Code built-in shell task so you can follow the VS Code doc to customize your own options.

Sample

{
  "label": "Install Azure Functions binding extensions",
  "type": "shell",
  "command": "dotnet extensions.csproj -o ./bin --ignore-failed-sources",
  "options": {
    "cwd": "${workspaceFolder}/api",
    "env": {
      "PATH": "${command:fx-extension.get-dotnet-path}${env:PATH}"
    }
  },
  "presentation": {
    "reveal": "silent"
  }
}

Note: the ${command:fx-extension.get-dotnet-path} variable reference is to get dotnet path installed by Teams Toolkit (from the Validate & Install prerequisites task).

Start local tunnel

This task is to start local tunnel service (ngrok) to make your local bot message endpoint public.

Arguments Type Required Description
ngrokArgs string or string[] required The ngrok command line arguments to start the tunnel. Full references can be found in ngrok document.
tunnelInspection string optional Teams Toolkit tries to get tunnel public URL from ngrok log first, then the first PublicURL via default inspection "http://127.0.0.1:4040/api/tunnels". If you specify your own ngrokArgs with different log format or inspection, set this arg to provide your own inspection location.

Sample

1. The default one used by TeamsFx templates. Teams Toolkit installs its own ngrok binary and start tunnel with command ngrok http 3978 --log=stdout --log-format=logfmt.

{
    "label": "Start local tunnel",
    "type": "teamsfx",
    "command": "debug-start-local-tunnel",
    "args": {
        "ngrokArgs": "http 3978 --log=stdout --log-format=logfmt",
    },
    "isBackground": true,
    "problemMatcher": "$teamsfx-local-tunnel-watch"
},

2. Change port. To use another port for local bot service (e.g., 3922), you can change the one in ngrokArgs. Note that you also need to change the port in bot code (index.js or index.ts).

{
    "label": "Start local tunnel",
    "type": "teamsfx",
    "command": "debug-start-local-tunnel",
    "args": {
        // change port here
        "ngrokArgs": "http 3922 --log=stdout --log-format=logfmt",
    },
    "isBackground": true,
    "problemMatcher": "$teamsfx-local-tunnel-watch"
},

3. Use your own ngrok command or config. If you'd like to use your own ngork command (e.g., ngrok start) or config (e.g., any-ngrok.yml) for advances usages. Note that if you change the log format or set your own inspect path, you need to provide tunnelInspection as well.

{
    "label": "Start local tunnel",
    "type": "teamsfx",
    "command": "debug-start-local-tunnel",
    "args": {
        // change the command here
        "ngrokArgs": "start --config any-ngrok.yml",
        // to let Teams Toolkit know your ngrok endpoint
        "tunnelInspection": "http://127.0.0.1:4040/api/tunnels",
    },
    "isBackground": true,
    "problemMatcher": "$teamsfx-local-tunnel-watch"
},

4. Use your own ngrok binary. Start your own ngrok with command ngrok http 3978 in the terminal and set the ngrok endpoint into the botMessagingEndpoint.

{
    "label": "Start Teams App Locally",
    "dependsOn": [
        ...
        // Remove/Comment out tunnel task
        //"Start local tunnel",
        "Set up bot",
        ...
    ],
    "dependsOrder": "sequence"
},
...
{
    "label": "Set up bot",
    "type": "teamsfx",
    "command": "debug-set-up-bot",
    "args": {
        ...
        // tell Teams Toolkit your message endpoint
        "botMessagingEndpoint": "https://sample-id.ngrok.io/api/messages",
    }
},

5. Totally get rid of ngrok. If your dev environment does not support ngrok or you'd like to use your own tunnel solution, you can skip/remove this tunnel task and just let Teams Toolkit know your message endpoint.

Alternative Description
Cloud VM Develop your project on cloud VM (e.g., Azure VMs or Azure DevTest Labs). You can choose either to still use ngrok on your cloud VM, or to directly expose your bot service via VM's public hostname and port.
localtunnel An alternative tunnel solution. You can install and run localtunnel instead of ngrok.
{
    "label": "Start Teams App Locally",
    "dependsOn": [
        ...
        // Remove/Comment out tunnel task
        //"Start local tunnel",
        "Set up bot",
        ...
    ],
    "dependsOrder": "sequence"
},
...
{
    "label": "Set up bot",
    "type": "teamsfx",
    "command": "debug-set-up-bot",
    "args": {
        ...
        // tell Teams Toolkit your message endpoint
        "botMessagingEndpoint": "https://you-bot-host/api/messages",
    }
},

Set up Tab

This task is to prepare local launch information for Tab.

Arguments Type Required Description
baseUrl string required The base url that the Tab app will be hosted on.

Sample

{
  "label": "Set up Tab",
  "type": "teamsfx",
  "command": "debug-set-up-tab",
  "args": {
    "baseUrl": "https://localhost:53000"
    //// or use your own local port
    // "baseUrl": "https://localhost:23000",
  }
}

Set up Bot

This task is to register resources and prepare local launch information for Bot.

Arguments Type Required Description
botId string optional The Microsoft Entra app client id for bot. Set this argument to use an existing bot.
botPassword string optional The Microsoft Entra app client secret for bot. Set this argument to use an existing bot.
botMessagingEndpoint string required The bot messaging endpoint. If without hostname (e.g., api/messages), Teams Toolkit uses the ngrok host from Start Local Tunnel task. If with hostname (e.g., https://contoso.com/api/messages), Teams Toolkit uses the provided full URL.

Sample

{
  "label": "Set up Bot",
  "type": "teamsfx",
  "command": "debug-set-up-bot",
  "args": {
    //// Use your own Microsoft Entra App for bot
    // "botId": "",
    // "botPassword": "", // use plain text or environment variable reference like ${env:BOT_PASSWORD}
    "botMessagingEndpoint": "api/messages"
  }
}

Set up SSO

This task is to register resources and prepare local launch information for SSO functionality.

Arguments Type Required Description
clientId string optional The Microsoft Entra app client id for SSO. Set this argument to use an existing Microsoft Entra App.
clientSecret string optional The Microsoft Entra app client secret for SSO. Set this argument to use an existing Microsoft Entra App.
objectId string optional The Microsoft Entra app object id for SSO. Set this argument to use an existing Microsoft Entra App.
accessAsUserScopeId string optional The Microsoft Entra app access_as_user scope id for SSO. Set this argument to use an existing Microsoft Entra App.

Sample

{
  "label": "Set up SSO",
  "type": "teamsfx",
  "command": "debug-set-up-sso",
  "args": {
    //// Use your own Microsoft Entra App for SSO
    // "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    // "clientSecret": "plain-text or ${env:YOUR_CLIENT_SECRET}",
    // "objectId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    // "accessAsUserScopeId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  }
}

Build & Upload Teams manifest

This task is to build then upload Teams App manifest. If you specfic your own app package path, it skips building package but directly upload your own package.

Argument Type Required Description
appPackagePath string optional Teams app package path. If undefined, Teams Toolkit will build and upload the manifest according to the template in templates/appPackage/manifest.template.json. If the value is a .zip file path, Teams Toolkit will upload the Teams app package without building.

Sample

{
  "label": "Build & Upload Teams manifest",
  "type": "teamsfx",
  "command": "debug-prepare-manifest",
  "args": {
    //// Enter your own Teams app package path if using the existing Teams manifest. ////
    // "appPackagePath": "/path/to/your/appPackage.zip"
  }
}

Start services

These tasks are standard VS Code shell tasks to execute npm commands on sub-projects, following the official schema defined by VS Code. For example,

  • command defines the shell command to be executed
  • isBackground: true means the task keeps running in the background
  • problemMatcher is used to capture the begin/end or any problem from the task output

Sample

{
    "label": "Start services",
    "dependsOn": [
        "Start frontend",
        "Start backend",
        "Start bot"
    ]
},
{
    "label": "Start frontend",
    "type": "shell",
    "command": "npm run dev:teamsfx",
    "isBackground": true,
    "options": {
        "cwd": "${workspaceFolder}/tabs"
    },
    "problemMatcher": {
        "pattern": {
            "regexp": "^.*$",
            "file": 0,
            "location": 1,
            "message": 2
        },
        "background": {
            "activeOnStart": true,
            "beginsPattern": ".*",
            "endsPattern": "Compiled|Failed"
        }
    }
},
{
    "label": "Start backend",
    "type": "shell",
    "command": "npm run dev:teamsfx",
    "isBackground": true,
    "options": {
        "cwd": "${workspaceFolder}/api",
        "env": {
            "PATH": "${command:fx-extension.get-func-path}${env:PATH}"
        }
    },
    "problemMatcher": {
        "pattern": {
            "regexp": "^.*$",
            "file": 0,
            "location": 1,
            "message": 2
        },
        "background": {
            "activeOnStart": true,
            "beginsPattern": "^.*(Job host stopped|signaling restart).*$",
            "endsPattern": "^.*(Worker process started and initialized|Host lock lease acquired by instance ID).*$"
        }
    },
    "presentation": {
        "reveal": "silent"
    }
},
{
    "label": "Start bot",
    "type": "shell",
    "command": "npm run dev:teamsfx",
    "isBackground": true,
    "options": {
        "cwd": "${workspaceFolder}/bot"
    },
    "problemMatcher": {
        "pattern": {
            "regexp": "^.*$",
            "file": 0,
            "location": 1,
            "message": 2
        },
        "background": {
            "activeOnStart": true,
            "beginsPattern": "[nodemon] starting",
            "endsPattern": "app listening to|Bot/ME service listening at|[nodemon] app crashed"
        }
    },
    "presentation": {
        "reveal": "silent"
    }
}

Upgrade your old Teams Toolkit project to use new tasks

Both old tasks and new tasks define the same F5 flow, so it's easy to upgrade old tasks to new tasks - just replace old task with the equivalent new task(s).

For quick replacement, here are tasks.json samples that you can directly reference to overwrite the existing one.

Project Type Project Language
(JavaScript)
Project Language
(TypeScript)
Tab
  • SSO Enabled
tasks.json tasks.json
Tab
  • Without SSO
tasks.json tasks.json
Bot
  • Notification (Express Hosted)
  • Command
  • Workflow
  • Message Extension
tasks.json tasks.json
Bot
  • Notification (Function Hosted)
tasks.json tasks.json
SPFx tasks.json tasks.json

Or, if you'd like to replace partial tasks, follow this mapping between old tasks and new tasks:

Old Task New Task(s)
validate local prerequisites
  • Validate & Install prerequisites (teamsfx:debug-check-prerequisites)
  • Install NPM packages (teamsfx:debug-npm-install)
  • * Install Azure Functions binding extensions (shell:dotnet ...) - this is optional and only required if you have *api/* sub-project.
  • start ngrok
  • Start local tunnel (teamsfx:debug-start-local-tunnel)
  • prepare local environment
  • * Set up tab (teamsfx:debug-set-up-tab) - required if you have tabs/_ sub-project.
  • _ Set up bot (teamsfx:debug-set-up-bot) - required if you have bot/ sub-project.
  • Set up SSO (teamsfx:debug-set-up-sso) - required if you enable SSO feature in your project.
  • Build & Upload Teams manifest (*teamsfx:debug-prepare-manifest*)
  • Note: After replacing these tasks, update the entry task's dependsOn property to use new tasks as well. E.g.,

    {
        "version": "2.0.0",
        "tasks": [
            {
                "label": "Pre Debug Check & Start All",
                "dependsOn": [
                    //// remove the old ones
                    // "validate local prerequisites",
                    // "prepare local environment",
                    //// add new ones
                    "Validate & install prerequisites",
                    "Install npm packages",
                    // "Start local tunnel",
                    "Set up tab",
                    // "Set up bot",
                    // "Set up SSO",
                    "Build & upload Teams manifest",
                    "Start All"
                ],
                "dependsOrder": "sequence"
            },
    ...

    Or, if your project structure did not change too much, you can create a new empty project with all your features/components, and replace the whole .vscode/tasks.json file with the newly generated one. (Since the entry task label changes, you will need to update "preLaunchTask" property in .vscode/launch.json as well.)

    Frequently Asked Questions

    How to customize the service ports?

    For frontend:

    1. Change portOccupancy argument in Validate & Install prerequisites task.
    2. Set baseUrl argument in Set up tab task.

    For bot:

    1. Set the port value in bot service code or set the port environment variable in bot/.env.teamsfx.local.
    2. Change portOccupancy argument in Validate & Install prerequisites task.
    3. Change ngrokArgs argument in Start local tunnel task.

    For backend:

    1. Set the port value in the start script in api/package.json.
    2. Change portOccupancy argument in Validate & Install prerequisites task.
    3. If SSO is enabled, set the REACT_APP_FUNC_ENDPOINT environment variable in tabs/.env.teamsfx.local, and set the API_ENDPOINT environment variable in api/.env.teamsfx.local.
    4. If SSO is enabled and bot is included, set the API_ENDPOINT environment variable in bot/.env.teamsfx.local.

    For SPFx:

    1. Change the port value in SPFx/config/serve.json
    2. Change portOccupancy argument in Validate & Install prerequisites task.
    3. Change the staticTabs.contentUrl and configurableTabs.configurationUrl arguments in templates/appPackage/manifest.template.json.

    How to use the existing Microsoft Entra app for SSO?

    1. Set objectId, clientId, clientSecret and accessAsUserScopeId arguments in Set up SSO task. For clientSecret, use plain text or environment variable reference like ${env:CLIENT_SECRET}.
    2. If bot is included, set the M365_CLIENT_SECRET environment variable in bot/.env.teamsfx.local.
    3. If backend is included, set the M365_CLIENT_SECRET environment variable in api/.env.teamsfx.local.

    How to use the existing bot?

    1. Set botId and botPassword arguments in Set up bot task.

    How to use my own bot messaging endpoint?

    1. Remove Start local tunnel dependency from Start Teams App Locally task.
    2. Remove ngrok option in prerequisites argument in Validate & install prerequisites task.
    3. Set the botMessagingEndpoint argument in Set up bot task.

    How to install the packages for an existing app which the package manager is not npm?

    If the package manager is yarn, PNPM or other tools, user can use a self-defined task instead.

    Sample

    {
        "label": "install packages",
        "type": "shell",
        "command": "yarn"
        "options": {
            "cwd": "${workspaceFolder}"
        }
    }
    
    Clone this wiki locally