- Background
- Contributing Guidelines
- Development Environments
- Build
- Frontend Development
- Backend Development
- Application Monitoring and Telemetry
Retrospectives is an Azure DevOps extension. Visit this link to learn more about developing extensions. The Retrospectives Azure DevOps extension frontend is implemented in React using Typescript, and the backend is implemented in C#. The project follows a single branch source control strategy.
-
When creating a new branch, follow the
{alias}/{issue##}
naming convention. - Note: It is recommended to keep the branch name length below 30 characters in order to allow the Github Action which builds and deploys the development extension on Pull Request creation or update to successfully execute. -
Once your feature addition or bug fix is ready for review, create a pull request against the
main
branch of the repository. -
Include a link to the GitHub issue you are addressing to the description of your pull request. Reviewers will be added to the pull request automatically.
-
Ensure all CI/CD checks are successful after the creation of the pull request.
-
Update any documentation, user and contributor, that is impacted by your changes.
-
You may merge the pull request in once you have the sign-off from one developer from the Retrospectives team, or if you do not have permission to do that, you may request the reviewer to merge it for you.
Our CI pipeline can be invoked on Github, or if you want to get ahead of the potential failures, you
can use the pre-commit
configuration. It will run
linting on markdown files and python files, and run a spellcheck. The same rules will be caught locally
that will be caught in Github actions.
To use pre-commit
, it's recommended to have a python virtual environment (venv).
If the venv ends with -env
, such as retro-env
, then the .gitignore
is configured to not watch
this environment during development!
Either in the dev container or locally:
- Run:
pip install -r requirements.txt
- Run:
pre-commit install
- To run the checks ahead of commiting:
pre-commit run
will run the pre-commit hooks against staged filespre-commit run --all-files
will run against everythingpre-commit run markdownlint
to run the markdown lintingpre-commit run spellcheck-cli
to run the spellchecking
- To run linting for the typescript/javascript (must be done within the
RetrospectiveExtension.Frontend
directory):npm run lint
Read more about the python pre-commit framework. To disable the pre-commit
hook run pre-commit uninstall
from the root folder.
The Retrospectives Extension can be built, developed and tested in several development environments. This section highlights three of the primary environments in order of relevance.
All of the development prerequisites, such as Webpack and NodeJS are listed in the Dockerfile. This file can be opened in a text editor and the install commands can be used to configure the prerequisites outside of a dev container.
-
Install the latest version of Docker Desktop.
-
Install the latest version of Visual Studio Code.
-
Install the Docker extension for Visual Studio Code.
-
Install the Remote - Containers extension for Visual Studio Code.
-
Check out this repository and open the parent folder in Visual Studio Code.
-
Follow the steps outlined in the Build section to build, test, and deploy development versions of the extension.
- The first time this repository is opened in Visual Studio Code, the
.devcontainer
folder will be detected. In the bottom right-hand corner of the screen, a prompt will be displayed: “Folder contains a Dev Container configuration file. Reopen folder to develop in a container.”. - Selecting the “Reopen in Container” option will automatically start the process of creating the Dev Container; this may take a few minutes the first time the container is created, or any time the settings for the container have changed and the container needs to be recreated.
- If there are issues running the
ci.sh
script in a clean checkout, check theFiles: Eol
setting in Visual Studio Code. Change it to \n, open theci.sh
file, save it, and retry the script.
-
To configure the WSL if it is not already available on the development machine, follow this tutorial.
-
Follow Git on WSL Instructions if Git is not already installed on the development machine.
-
Follow Node Installation Instructions to enable Node for WSL.
-
Install the latest version of Visual Studio Code.
-
Install the Remote – WSL extension for Visual Studio Code.
-
Check out this repository and open the parent folder in Visual Studio Code.
-
If VSCode does not recognize the WSL on its own, in the top right hand corner of the terminal window, select the down arrow to "Launch Profile..." and select the name of the distribution in use to create a new WSL terminal.
-
Perform the commands listed in the Dockerfile to globally install required packages such as dotnet core.
-
Run the setup_ci.sh script to configure the WSL for the pre-commit hook.
-
Follow the steps outlined in the Build section to build, test, and deploy development versions of the extension.
- Some commands, such as
dotnet build
andnpm run build:p
may needsudo
prefixed to execute successfully.
-
If necessary, read GitHub's codespace creation documentation.
-
Create a branch for the work you are planning to complete.
-
Create a codespace through the new branch's dropdown on GitHub.
-
Codespaces are powered by Visual Studio Code and dev containers - once the codespace has been entered, you can follow the instructions within the dev containers section for continuing to set up the development environment. View the Developing in a codespace documentation for additional details.
Test changes in the Azure DevOps environment by publishing a development version of the extension under an Azure DevOps publisher account.
-
Clone this repository, and open in your preferred development environment.
-
Using Powershell, navigate to the
/RetrospectiveExtension.Frontend
folder, runnpm install
. This will download all the dependent packages listed inpackage.json
. -
When developing or publishing the extension locally, you need to create a .env file at the top-level directory of the front end project (where
package.json
lives). You can copyRetrospectiveExtension.Frontend/.env.template
toRetrospectiveExtension.Frontend/.env
to get started. The contents of the.env
file are# Backend Service URL REACT_APP_COLLABORATION_STATE_SERVICE_URL="put the deployed backend service url here" # App Instrumentation Key REACT_APP_APP_INSIGHTS_INSTRUMENTATION_KEY="put Instrumentation key here"
-
In lieu of the .env file you can set actual environment variables.
-
When using the CI/CD github action(s) pipeline to deploy the extension, environment variables are used to set Application Insights instrumentation key and the backend service url.
-
-
Run
npm run build:d
ornpm run build:p
to build the project. The difference in commands isdevelopment
versusproduction
, respectively; theproduction
command will generate a smaller bundle. -
To test your changes, you will need to publish a new extension under a new Azure DevOps publisher account. Refer to the documentation on publishing extensions. You can publish it to any test Azure DevOps organization that you are an admin of (As a Microsoft employee, you can create a new test organization from your Azure DevOps profile page). Currently this is the only way to test the extension.
-
Copy the file
vss-extension-dev.json.template
into a newvss-extension-dev.json
file with the new publisher that you setup. Also update the name and id fields.{ "manifestVersion": 1, "id": <any new id>, "publisher": <the new publisher you created>, "version": <your staring version>, "name": <your extension's name. Can be any name you can identify by. Eg. Retrospectives-test>, }
-
Run
npm run pack:d
to package the modules into a Azure DevOps extension package. This generated package has a.vsix
extension. This package is generated using information from the manifest file and your built code. Refer to the documentation to know more about extension manifests. -
Publish your to the marketplace. Once published, share the extension with the newly created test org. See this link for documentation on sharing.
-
Once the extension has been shared with your test org, you can install it to your org and start using it. This installation process is similar to installing any other DevOps extensions. Refer to this link for instructions. Since the extension is still in preview mode, it needs to be enabled for the Azure DevOps project. Enable the extension from the
Preview Features
tab. -
Now start using the extension to test your changes.
-
For updates, rebuild and package your extension and publish an update from the Azure DevOps marketplace. That will automatically update the extension in your project.
-
For the real time live syncing to work, our service needs to know your publisher id and your extension's unique key. To enable real time updates for your test extension, please reach out to us with your publisher id and the unique key of your extension.
Test changes by loading changes locally without having to re-package and re-publish the extension in the marketplace.
-
Debugger for Firefox VS Code extension
-
In the
RetrospectiveExtension.Frontend
folder, create thevss-extension-dev.json
file using the template filevss-extension-dev.json.template
for reference. -
Update the
webpack.config.js
to enable source maps. Set the devtool property toinline-source-map
. Also setdevServer.https
to true and devServer.port to 3000.module.exports = { devtool: 'inline-source-map', devServer: { https: true, port: 3000, static: { directory: path.join(__dirname), } }, ...
-
Set
output.publicPath
to/dist/
in the webpack.config.json file. This will allow webpack to serve files fromhttps://localhost:3000/dist
.module.exports = { output: { publicPath: "/dist/" // ... } // .. };
-
In the root of the project, create a folder named
.vscode
. In there, create a file namedlaunch.json
, which will help to set up a debug configuration for VS Code that launches Firefox with the correct path mappings. Inside of this file, you will add a path mapping withurl
set towebpack:///
and have the path set to${workspaceFolder}/RetrospectiveExtension.Frontend/
. Also set the reAttach property on the configuration to true to avoid restarting Firefox every time you debug.{ "version": "0.2.0", "configurations": [ { "name": "Launch Firefox", "type": "firefox", "request": "launch", "url": "https://localhost:3000/", "reAttach": true, "pathMappings": [ { "url": "webpack://retrospective-vsts-extension/components", "path": "${workspaceFolder}/RetrospectiveExtension.Frontend/components" }, { "url": "webpack://retrospective-vsts-extension/dal", "path": "${workspaceFolder}/RetrospectiveExtension.Frontend/dal" }, { "url": "webpack:///", "path": "${workspaceFolder}/RetrospectiveExtension.Frontend/" } ] } ] }
-
Navigate to the
/RetrospectiveExtension.Frontend
folder, runnpm install
to download all the dependent packages listed inpackage.json
. -
Run
npm run build:d
to build the project. -
Run
npm run start:dev
to start the webpack-dev-server -
Start debugger (making sure the webpack-dev-server is still running). The default launch configuration should be set to Launch Firefox.
-
IF YOU ARE ON WINDOWS -> Access Firefox settings from the hamburger menu. Navigate to
Privacy & Security
and underLogins and Passwords
selectAllow Windows single sign-on for Microsoft, work and school accounts
. This is necessary to login to Azure otherwise you will be blocked by a Microsoft management policy for Firefox. This step needs to be completed each time you launch the debugger as it launches Firefox with a cleared cache and default settings. -
Once Firefox starts up, you should get an untrusted certificate error page. Select Advanced and then select Accept the Risk and Continue and log into your Azure DevOps account. From now on, if you leave this Firefox window open, the debugger will reattach instead of starting a clean Firefox instance each time.
-
Once you are logged in to Azure DevOps, your extension should be running. Set a breakpoint in a method in VS Code and you should see that breakpoint hit when that method executes.
The Retrospectives extension uses the Azure SignalR service to add real time support. The backend codebase can be found here.
To enable real time updates from your test extension you will need to deploy the backend to Azure specifying your publisher id and the unique key of your extension.
- This setup is not required for contributing to this extension, but can be helpful if you want certain debugging options available to you.
- If you are part of a team working on the Retrospectives extension you can deploy a single backend to support multiple developer test extensions.
-
Azure CLI - installation instructions here
-
dotnet CLI - the CLI comes as a part of the .NET SDK
-
the
zip
CLI tool - viabrew install zip
orapt-get install zip
in a unix-flavored environment.
-
Copy
/deploy/.env.template
to/deploy/.env
and make the following changes:- Add the Service Principal values used by the
env_setup.sh
script. Instructions on how to create a Service Principal. - Add the
RESOURCE_NAME_SUFFIX
value. This will be used for naming all Azure resources including the App Service name -https://<RESOURCE_NAME_SUFFIX>.azurewebsites.net
. Note: The app name must be globally unique so select something accordingly. - Add the
LOCATION
value i.e. "eastus", "westus", etc.
- Add the Service Principal values used by the
-
Copy
/allowed_origins.json.template
to/allowed_origins.json
and replace the<publisher id>
with your publisher id. This id uniquely identifies your publisher in the Visual Studio Marketplace. If you are part of a team working on the retro tool you can add additional allowed origins. There should be two allowed origins per publisher id. Remember to increment the name index as you add additional origins. -
Copy
/dev_certs.json.template
to/dev_certs.json
and replace the<extension secret>
with your secret. Instructions on how to download the unique key. If you are part of a team working on the retro tool you can add additional secrets. Remember to increment the name index to add additional secrets. -
Run the
deploy/env_setup.sh
script. -
Once the script completes, it will output the url of the backend service. You can navigate to the Azure Portal and validate that the
rg-<RESOURCE_NAME_SUFFIX>
resource group exists and contains the App Service, App Service Plan and SignalR resources. -
Update the
RetrospectiveExtension.FrontEnd/config/environment.tsx
to reflect changes to:CollaborationStateServiceUrl
value to the App Service URL -https://<RESOURCE_NAME_SUFFIX>.azurewebsites.net
.AppInsightsInstrumentKey
value to Application Insights' Instrumentation Key for the resourceai-<RESOURCE_NAME_SUFFIX>
.
-
After updating the above values redeploy the extension.
This extension uses ESLint for consistent formatting and styling within the React components.
React Component tests are written using the following packages:
To automatically generate the test coverage report, add the --coverage
flag
to the test
script defined in
package.json. After the test
run is completed, coverage statistics will then be reported in the newly
created coverage
directory.
npm install
must be executed before running any tests.npm run test
is the default test execution method defined in the package.json file. This will automatically run all of the tests in files suffixed with.test.tsx
inside of the tests folder.npm run test:watch
will run tests in watch mode, re-running tests every time a component change is saved.jest --env=jsdom --silent -ci --testResultsProcessor=jest-junit {FULL_FILE_PATH}
can be used to run tests only in the specified file. Wildcards also work instead of a fully qualified path.
- In this project, mocks have been implemented for simulating API calls and external module functionality. Reusable mocks should be added to the mock folder.
- Mocks which are shared by the majority of tests should be initialized in the test setup file.
To ensure proper rendering of components, snapshots tests are being used to compare expected component rendering state against its actual state. Snapshot tests will fail when changes are made to components that are not accounted for through updates to these stored snapshots.
To update snapshots, delete the snapshot for the component you are testing, (located in the snapshots folder) and run the test command. On test run completion, new snapshots should be created. Please check the newly created snapshot file, to ensure that the expected changes are present, and include the snapshot in your pull request.
To enable real time updates from your test extension you will need to deploy the backend to Azure specifying your publisher id and the unique key of your extension. Note: If you are part of a team working on the retro tool you can deploy a single backend to support multiple developer test extensions.
- Copy
/deploy/.env.template
to/deploy/.env
and make the following changes:- Add the Service Principal values used by the
env_setup.sh
script. Instructions on how to create a Service Principal. - Add the
RESOURCE_NAME_SUFFIX
value. This will be used for naming all Azure resources including the App Service name -https://<RESOURCE_NAME_SUFFIX>.azurewebsites.net
. Note: The app name must be globally unique so select something accordingly. - Add the
LOCATION
value i.e. "eastus", "westus", etc.
- Add the Service Principal values used by the
- Copy
/allowed_origins.json.template
to/allowed_origins.json
and replace the<publisher id>
with your publisher id. This id uniquely identifies your publisher in the Visual Studio Marketplace. If you are part of a team working on the retro tool you can add additional allowed origins. There should be two allowed origins per publisher id. Remember to increment the name index as you add additional origins. - Copy
/dev_certs.json.template
to/dev_certs.json
and replace the<extension secret>
with your secret. Instructions on how to download the unique key. If you are part of a team working on the retro tool you can add additional secrets. Remember to increment the name index to add additional secrets. - Run the
deploy/env_setup.sh
script. - Once the script completes, it will output the url of the backend service. You can navigate to the
Azure Portal and validate that the
rg-<RESOURCE_NAME_SUFFIX>
resource group exists and contains the App Service, App Service Plan and SignalR resources. - Update the
RetrospectiveExtension.FrontEnd/config/environment.tsx
to reflect changes to:CollaborationStateServiceUrl
value to the App Service URL -https://<RESOURCE_NAME_SUFFIX>.azurewebsites.net
.AppInsightsInstrumentKey
value to Application Insights' Instrumentation Key for the resourceai-<RESOURCE_NAME_SUFFIX>
.
- After updating the above values redeploy the extension.
Follow the coding guidelines here - C# Coding Conventions (C# Programming Guide).
The Retrospectives tool uses the Azure DevOps data service for handling all its storage.
-
The project is developed using the .NET Core development platform. The
CollaborationStateService
web project contains the code for the backend service. Since .NET Core is platform independent, project can be developed on any operating system. -
The
ReflectBackend.ReflectHub
class contains the implementation of all the functions that the backend service supports. New methods should be added here to support more real time scenarios. -
Examples:
-
The code snippet below provides a method that the client can use to join a backend Group. Groups in SignalR provide a method for broadcasting messages to specified subsets of connected clients. Any client using this method gets added to the group that it specifies by the reflectBoardId.
/// <summary> /// Adds the client to the group for this reflect board. /// </summary> /// <param name="reflectBoardId">The id of the reflect board.</param> public Task JoinReflectBoardGroup( string reflectBoardId ) { _insights.TrackEvent("Adding client to board"); return Groups.AddToGroupAsync( Context.ConnectionId, reflectBoardId ); }
-
The code snippet below broadcasts that a new Feedback specified by the
feedbackItemId
is available on the board specified byreflectBoardId
. ThecolumnId
specifies which column of the board the item was added to. Clients can use this method to signal to other clients that a new Feedback was added to one of its boards./// <summary> /// Broadcast receiveNewItem to all other clients viewing the same reflect board. /// </summary> /// <param name="reflectBoardId">The id of the reflect board.</param> /// <param name="columnId">The id of column this item is associated with.</param> /// <param name="feedbackItemId">The id of the new feedback item.</param> public Task BroadcastNewItem( string reflectBoardId, string columnId, string feedbackItemId ) { _insights.TrackEvent("Broadcasting new item"); return Clients.OthersInGroup( reflectBoardId ).SendAsync( "receiveNewItem", columnId, feedbackItemId ); }
-
Unit Tests for the Backend are located in the Backend Tests folder. To execute these tests, perform the following steps:
-
Navigate to the
RetrospectiveExtension.Backend
folder. -
Execute
dotnet restore
. -
Execute
dotnet build
. -
Execute
dotnet test ../RetrospectiveExtension.Backend.Tests
. -
View test results in the terminal.
-
The Retro tool uses Azure Application Insights to capture application logs, telemetry and performance data.
-
A custom Azure portal is deployed as part of the backend deployment script that enables real time monitoring of the application. The dashboard includes useful telemetry data such as number of active user sessions, histogram of React Components visited, HTTP requests made, page load times, backend and front end exceptions and other metrics.
Copyright (c) Microsoft Corporation. All rights reserved.