Hi everyone!
Maintaining the
Retrospective Extension for Azure DevOpshas been a passion project we’ve pursued in our personal time. While we’ll continue to handle security updates and occasional feature improvements when we can, our available time is limited. To help take the project to the next level, we’d love to invite contributors to join us in making it even better for the community.If you're interested in contributing, please check out the repo and the Contributing Guideline! Together, we can ensure the project continues to thrive! 🚀
- Background
- Ways to Contribute
- Contributing Guidelines
- Development Environments
- Build
- Frontend Development
- Backend Development
- Application Monitoring and Telemetry
Retrospectives is an Azure DevOps extension. Visit the Azure DevOps Extension overview 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.
There are several ways you can contribute to the Retrospectives extension:
If you encounter bugs, have feature requests, or need help with the extension, please visit the GitHub Issues page. When reporting an issue:
- Search existing issues to avoid duplicates
- Use the appropriate issue template
- Provide clear steps to reproduce the problem
- Include relevant screenshots or error messages
- Specify your browser, Azure DevOps version, and extension version
You can help other users by participating in community discussions:
- GitHub Discussions: Join conversations and share insights at the GitHub Discussions page
- GitHub Issues: Help answer questions and provide solutions in existing GitHub Issues
- Share your experience and best practices with the extension
- Help troubleshoot problems reported by other users
If you want to contribute code changes, bug fixes, or new features:
- Follow the Contributing Guidelines outlined in this document
- Read through the Development Environments section to set up your local development environment*
- Review the Frontend Development and Backend Development sections for specific guidance
- Ensure your changes include appropriate tests and documentation
*Alternatively, watch the Azure DevOps Retrospective Extension - Setting Up Development Environment video for instructions on setting up your development environment.
-
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
mainbranch 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 runwill run the pre-commit hooks against staged filespre-commit run --all-fileswill run against everythingpre-commit run markdownlintto run the markdown lintingpre-commit run spellcheck-clito run the spellchecking
-
To run linting for the typescript/javascript (must be done within the
src/frontenddirectory):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, are listed in the DevContainer Configuration. This file can be opened in a text editor and the tools and extensions can be used to configure the prerequisites outside of a dev container.
-
Install the latest version of 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
.devcontainerfolder 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.shscript in a clean checkout, check theFiles: Eolsetting in Visual Studio Code. Change it to \n, open theci.shfile, 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.
-
Follow the steps outlined in the Build section to build, test, and deploy development versions of the extension.
- Some commands, such as
dotnet buildandnpm run buildmay needsudoprefixed 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
/src/frontendfolder, 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.jsonlives). You can copysrc/frontend/.env.templatetosrc/frontend/.envto 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:dornpm run build:pto build the project. The difference in commands isdevelopmentversusproduction, respectively; theproductioncommand 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.templateinto a newvss-extension-dev.jsonfile 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:dto package the modules into a Azure DevOps extension package. This generated package has a.vsixextension. 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 package 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 Featurestab. -
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
src/frontendfolder, create thevss-extension-dev.jsonfile using the template filevss-extension-dev.json.templatefor reference. -
Update the
webpack.config.jsto enable source maps. Set the devtool property toinline-source-map. Also setdevServer.httpsto true and devServer.port to 3000.module.exports = { devtool: 'inline-source-map', devServer: { https: true, port: 3000, static: { directory: path.join(__dirname), } }, ...
-
Set
output.publicPathto/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 withurlset towebpack:///and have the path set to${workspaceFolder}/src/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}/src/frontend/components" }, { "url": "webpack://retrospective-vsts-extension/dal", "path": "${workspaceFolder}/src/frontend/dal" }, { "url": "webpack:///", "path": "${workspaceFolder}/src/frontend/" } ] } ] } -
Navigate to the
/src/frontendfolder, runnpm installto download all the dependent packages listed inpackage.json. -
Run
npm run build:dto build the project. -
Run
npm run start:devto 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 & Securityand underLogins and PasswordsselectAllow 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 in the Retrospectives Extension Backend Repository.
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
zipCLI tool - viabrew install ziporapt-get install zipin a unix-flavored environment.
-
Copy
/deploy/.env.templateto/deploy/.envand make the following changes:- Add the Service Principal values used by the
env_setup.shscript. Instructions on how to create a Service Principal. - Add the
RESOURCE_NAME_SUFFIXvalue. 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
LOCATIONvalue i.e., "eastus", "westus", etc.
- Add the Service Principal values used by the
-
Copy
/allowed_origins.json.templateto/allowed_origins.jsonand 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.templateto/dev_certs.jsonand 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.shscript. -
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
src/frontend/config/environment.tsxto reflect changes to:CollaborationStateServiceUrlvalue to the App Service URL -https://<RESOURCE_NAME_SUFFIX>.azurewebsites.net.AppInsightsInstrumentKeyvalue 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 installmust be executed before running any tests.npm run testis the default test execution method defined in the package.json file. This will automatically run all of the tests in files suffixed with.test.tsxinside of the tests folder.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.
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
CollaborationStateServiceweb project contains the code for the backend service. Since .NET Core is platform independent, project can be developed on any operating system. -
The
ReflectBackend.ReflectHubclass 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
feedbackItemIdis available on the board specified byreflectBoardId. ThecolumnIdspecifies 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.Backendfolder. -
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.