├── .gitignore ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── README.md ├── azure ├── api │ ├── icon-dark.png │ └── icon-light.png ├── board.png ├── code │ ├── icon-dark.png │ └── icon-light.png ├── license.md ├── projects │ ├── doc │ │ ├── 01.png │ │ ├── 02.png │ │ ├── 03.png │ │ ├── 04.png │ │ ├── 05.png │ │ └── 06.png │ ├── icon-dark.png │ └── icon-light.png └── radar │ ├── icon-dark.png │ └── icon-light.png ├── build.ps1 ├── configs ├── dev.json └── release.json ├── front ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── app.tsx │ ├── components │ │ ├── api-docs │ │ │ ├── api-modal.scss │ │ │ ├── api-modal.tsx │ │ │ ├── api-panel.scss │ │ │ └── api-panel.tsx │ │ ├── code-quality │ │ │ ├── code-panel.scss │ │ │ └── code-panel.tsx │ │ ├── project │ │ │ ├── project-modal.scss │ │ │ ├── project-modal.tsx │ │ │ ├── project-panel.scss │ │ │ └── project-panel.tsx │ │ └── template │ │ │ ├── template-panel.scss │ │ │ └── template-panel.tsx │ ├── index.tsx │ ├── model │ │ ├── api.ts │ │ ├── buildOptions.ts │ │ ├── code.ts │ │ ├── project.ts │ │ ├── sonar.ts │ │ ├── stacks.ts │ │ ├── template.ts │ │ └── user.ts │ ├── pages │ │ ├── api-docs │ │ │ ├── api-page-settings.tsx │ │ │ ├── api-page.scss │ │ │ └── api-page.tsx │ │ ├── code-quality │ │ │ ├── code-page-settings.tsx │ │ │ ├── code-page.scss │ │ │ └── code-page.tsx │ │ ├── project │ │ │ ├── projects-page-settings.tsx │ │ │ ├── projects-page.scss │ │ │ └── projects-page.tsx │ │ └── radar │ │ │ ├── radar.scss │ │ │ └── radar.tsx │ ├── react-app-env.d.ts │ ├── services │ │ ├── api.ts │ │ ├── code.ts │ │ ├── pipeline.ts │ │ ├── project.ts │ │ ├── registration.ts │ │ ├── repository.ts │ │ ├── services.ts │ │ ├── sonar.ts │ │ ├── storage.ts │ │ └── template.ts │ └── utils │ │ └── extensions.ts └── tsconfig.json ├── package-lock.json ├── tasks ├── stack-board-replaces │ ├── icon.png │ ├── package-lock.json │ ├── package.json │ ├── stackboardreplaces.ts │ ├── task.json │ └── tsconfig.json └── stack-board-repos │ ├── package-lock.json │ ├── package.json │ ├── stackboardrepos.ts │ ├── task.json │ └── tsconfig.json └── vss-extension.json /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | */**/node_modules 5 | */**/.pnp 6 | .pnp.js 7 | 8 | # testing 9 | */**/coverage 10 | 11 | # production 12 | */**/build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | *.vsix 25 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "msjsdiag.debugger-for-chrome" 4 | ] 5 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | /** 3 | * Install Chrome Debugger Extension for Visual Studio Code to debug your components with the 4 | * Chrome browser: https://aka.ms/spfx-debugger-extensions 5 | */ 6 | "version": "0.2.0", 7 | "configurations": [{ 8 | "name": "Local workbench", 9 | "type": "chrome", 10 | "request": "launch", 11 | "url": "https://localhost:4321/temp/workbench.html", 12 | "webRoot": "${workspaceRoot}", 13 | "sourceMaps": true, 14 | "sourceMapPathOverrides": { 15 | "webpack:///.././src/*": "${webRoot}/src/*", 16 | "webpack:///../../../src/*": "${webRoot}/src/*", 17 | "webpack:///../../../../src/*": "${webRoot}/src/*", 18 | "webpack:///../../../../../src/*": "${webRoot}/src/*" 19 | }, 20 | "runtimeArgs": [ 21 | "--remote-debugging-port=9222" 22 | ] 23 | }, 24 | { 25 | "name": "Hosted workbench", 26 | "type": "chrome", 27 | "request": "launch", 28 | "url": "https://enter-your-SharePoint-site/_layouts/workbench.aspx", 29 | "webRoot": "${workspaceRoot}", 30 | "sourceMaps": true, 31 | "sourceMapPathOverrides": { 32 | "webpack:///.././src/*": "${webRoot}/src/*", 33 | "webpack:///../../../src/*": "${webRoot}/src/*", 34 | "webpack:///../../../../src/*": "${webRoot}/src/*", 35 | "webpack:///../../../../../src/*": "${webRoot}/src/*" 36 | }, 37 | "runtimeArgs": [ 38 | "--remote-debugging-port=9222", 39 | "-incognito" 40 | ] 41 | } 42 | ] 43 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | // Configure glob patterns for excluding files and folders in the file explorer. 4 | "files.exclude": { 5 | "**/.git": true, 6 | "**/.DS_Store": true, 7 | "**/bower_components": true, 8 | "**/node_modules": true, 9 | "**/build": true, 10 | 11 | "**/coverage": true, 12 | "**/lib-amd": true, 13 | "src/**/*.scss.ts": true, 14 | "**/*.vsix": true, 15 | }, 16 | "typescript.tsdk": ".\\node_modules\\typescript\\lib" 17 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## **Stack Board for Azure DevOps** 2 | 3 | Designed to speed up the start of new projects by development teams, Stack Board has a template-based process for creating repositories in Azure DevOps. 4 | 5 | It is possible to define several source code models, thus delivering architecture standards and software best practices. 6 | 7 | ![01.png](azure/projects/doc/01.png) 8 | 9 | ## **Features** 10 | 11 | - Creating repositories based on templates. 12 | - Creating Build and Release pipelines (Coming soon). 13 | - Technology Radar (Coming soon). 14 | 15 | ### **Template Catalog** 16 | 17 | ![03.png](azure/projects/doc/03.png) 18 | 19 | | Name | Description | 20 | | ----------------------- | --------------------------------------------------------------------------------------------------- | 21 | | Template | Name of template. e.g. **ASP.NET Core Api Service** | 22 | | Template Description | Description of the template. e.g. **Microservice Template for ASP.NET Core** | 23 | | Source Repository* | Repository with source code that will serve as the basis for projects ASP.NET Core | 24 | | Branch | Name of the branch the source code will be saved to. e.g. **develop**, **main** | 25 | | Replace Key | The keyword that will be changed when creating the project, such as solution name, namespaces, etc. | 26 | | Tags | Tags of technology, such as C#, API, SQLServer | 27 | | Requires authentication | If the source of the base repository is private, it must have its credentials for the git clone | 28 | 29 | * *Even for repositories within Azure DevOps itself, the **"Requires authentication"** field is mandatory to perform the process. 30 | 31 | ### **Create new project** 32 | 33 | ![02.png](azure/projects/doc/02.png) 34 | 35 | | Name | Description | 36 | | --------------- | --------------------------------------------------------------------- | 37 | | Template | Template previously created in the settings screen | 38 | | Name | Project name and word that will be used to replace files and contents | 39 | | Repository Name | Name of the repository that will be created in Azure DevOps | 40 | 41 | ### **Running** 42 | 43 | ![04.png](azure/projects/doc/04.png) 44 | 45 | ### **Successed** 46 | 47 | ![05.png](azure/projects/doc/05.png) 48 | 49 | ### **Requirements** 50 | 51 | - For the process of creating a project, we use Azure Pipelines to perform tasks with git commands, so the permission of the user **"Build Service"** in each **Team Project** must have the following options to **Allow**. 52 | 53 | - Contribute 54 | - Create branch 55 | - Force push 56 | 57 | ![06.png](azure/projects/doc/06.png) 58 | 59 | 60 | ## **License** 61 | 62 | Licensed under the MIT license. More information can be found by viewing the license [here](azure/license.md). -------------------------------------------------------------------------------- /azure/api/icon-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/api/icon-dark.png -------------------------------------------------------------------------------- /azure/api/icon-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/api/icon-light.png -------------------------------------------------------------------------------- /azure/board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/board.png -------------------------------------------------------------------------------- /azure/code/icon-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/code/icon-dark.png -------------------------------------------------------------------------------- /azure/code/icon-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/code/icon-light.png -------------------------------------------------------------------------------- /azure/license.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Luiz Lima 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /azure/projects/doc/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/projects/doc/01.png -------------------------------------------------------------------------------- /azure/projects/doc/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/projects/doc/02.png -------------------------------------------------------------------------------- /azure/projects/doc/03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/projects/doc/03.png -------------------------------------------------------------------------------- /azure/projects/doc/04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/projects/doc/04.png -------------------------------------------------------------------------------- /azure/projects/doc/05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/projects/doc/05.png -------------------------------------------------------------------------------- /azure/projects/doc/06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/projects/doc/06.png -------------------------------------------------------------------------------- /azure/projects/icon-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/projects/icon-dark.png -------------------------------------------------------------------------------- /azure/projects/icon-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/projects/icon-light.png -------------------------------------------------------------------------------- /azure/radar/icon-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/radar/icon-dark.png -------------------------------------------------------------------------------- /azure/radar/icon-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/azure/radar/icon-light.png -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | # npm run build --prefix front 2 | # npm run build --prefix tasks/stack-board-repos 3 | # npm run build --prefix tasks/stack-board-replaces 4 | 5 | tfx extension create --manifest-globs vss-extension.json --overrides-file ./configs/release.json --root ./ -------------------------------------------------------------------------------- /configs/dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "stack-board-dev", 3 | "name": "Stack Board DEV", 4 | "public": false, 5 | "baseUri": "https://localhost:3000" 6 | } 7 | -------------------------------------------------------------------------------- /configs/release.json: -------------------------------------------------------------------------------- 1 | { 2 | "galleryFlags": [ 3 | "Public" 4 | ], 5 | "public": true 6 | } -------------------------------------------------------------------------------- /front/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stack-board", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "Stack board extension for Azure DevOps", 6 | "author": "IT Team", 7 | "license": "ISC", 8 | "homepage": "./", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/llima/stack-board-extension.git" 12 | }, 13 | "bugs": { 14 | "url": "https://github.com/llima/stack-board-extension/issues" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "release": "npm run package-release", 20 | "package-release": "tfx extension create --manifest-globs ../vss-extension.json --overrides-file ../configs/release.json --root ../" 21 | }, 22 | "dependencies": { 23 | "@fluentui/example-data": "^8.2.3", 24 | "@fluentui/react": "^8.22.2", 25 | "@types/node": "^12.0.0", 26 | "@types/react": "^17.0.0", 27 | "@types/react-dom": "^17.0.0", 28 | "azure-devops-extension-api": "^1.152.3", 29 | "azure-devops-extension-sdk": "^2.0.10", 30 | "azure-devops-ui": "^2.167.7", 31 | "base-64": "^1.0.0", 32 | "guid-typescript": "^1.0.9", 33 | "react": "^17.0.2", 34 | "react-dom": "^17.0.2", 35 | "react-icons": "^4.2.0", 36 | "react-scripts": "4.0.3", 37 | "swagger-ui-react": "3.25.0", 38 | "typescript": "^4.1.2", 39 | "vss-web-extension-sdk": "^5.141.0" 40 | }, 41 | "devDependencies": { 42 | "base64-inline-loader": "^1.1.1", 43 | "node-sass": "^4.13.0", 44 | "tslint-react": "^4.0.0" 45 | }, 46 | "eslintConfig": { 47 | "extends": [ 48 | "react-app" 49 | ] 50 | }, 51 | "browserslist": { 52 | "production": [ 53 | ">0.2%", 54 | "not dead", 55 | "not op_mini all" 56 | ], 57 | "development": [ 58 | "last 1 chrome version", 59 | "last 1 firefox version", 60 | "last 1 safari version" 61 | ] 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /front/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llima/stack-board-extension/0855274f0f26bee127ddf814c5e163c48598ffe7/front/public/favicon.ico -------------------------------------------------------------------------------- /front/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Stack Board 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /front/src/app.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import * as DevOps from "azure-devops-extension-sdk"; 3 | 4 | import ProjectPage from './pages/project/projects-page'; 5 | import Radar from './pages/radar/radar'; 6 | 7 | import { IHostNavigationService } from 'azure-devops-extension-api/Common/CommonServices'; 8 | import Api from './pages/api-docs/api-page'; 9 | import Code from './pages/code-quality/code-page'; 10 | 11 | interface IAppState { 12 | page: string; 13 | } 14 | 15 | class App extends React.Component<{}, IAppState> { 16 | 17 | projectService = DevOps.getService( 18 | "ms.vss-features.host-navigation-service" 19 | ); 20 | 21 | constructor(props: {}) { 22 | super(props); 23 | 24 | DevOps.init(); 25 | this.state = {page: ""}; 26 | 27 | this.projectService.then(item => { 28 | item.getPageRoute().then(route => { 29 | this.setState({ page: route.routeValues["parameters"] }); 30 | }); 31 | }); 32 | } 33 | 34 | render() { 35 | 36 | const { page } = this.state; 37 | 38 | switch (page) { 39 | case "llima.stack-board.stack-board-hub": 40 | return (); 41 | case "llima.stack-board.tech-radar-hub": 42 | return (); 43 | case "llima.stack-board.api-docs-hub": 44 | return (); 45 | case "llima.stack-board.code-quality-hub": 46 | return (); 47 | default: 48 | return null; 49 | } 50 | } 51 | } 52 | 53 | export default App; 54 | -------------------------------------------------------------------------------- /front/src/components/api-docs/api-modal.scss: -------------------------------------------------------------------------------- 1 | @import "azure-devops-ui/Core/_platformCommon.scss"; 2 | 3 | .api-modal { 4 | 5 | &--group { 6 | margin-bottom: 20px; 7 | } 8 | &--content { 9 | padding-top: 20px; 10 | } 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /front/src/components/api-docs/api-modal.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './api-modal.scss'; 3 | 4 | import { TextField } from "azure-devops-ui/TextField"; 5 | import { IApi } from '../../model/api'; 6 | 7 | import { CustomDialog } from "azure-devops-ui/Dialog"; 8 | import { PanelContent, PanelFooter } from "azure-devops-ui/Panel"; 9 | import { CustomHeader, HeaderTitleArea } from 'azure-devops-ui/Header'; 10 | import { ButtonGroup } from 'azure-devops-ui/ButtonGroup'; 11 | import { Button } from 'azure-devops-ui/Button'; 12 | 13 | 14 | export interface IApiModalProps { 15 | show: boolean; 16 | onDismiss: any; 17 | onConfirm: any; 18 | api: IApi; 19 | } 20 | 21 | interface IApiModalState { 22 | nameValidation: string; 23 | } 24 | 25 | class ApiModal extends React.Component { 26 | 27 | constructor(props: IApiModalProps) { 28 | super(props); 29 | this.state = { 30 | nameValidation: "" 31 | }; 32 | } 33 | 34 | isDeleteValid(): boolean { 35 | return ( 36 | this.props.api.name.toLocaleLowerCase() === this.state.nameValidation.toLocaleLowerCase() 37 | ); 38 | } 39 | 40 | close(that: this) { 41 | that.setState({ nameValidation: "" }, () => { 42 | that.props.onDismiss(); 43 | }); 44 | } 45 | 46 | confirm(that: this) { 47 | that.setState({ nameValidation: "", }, () => { 48 | that.props.onConfirm(); 49 | }); 50 | } 51 | 52 | render() { 53 | 54 | const { nameValidation } = this.state; 55 | const { api } = this.props; 56 | 57 | if (this.props.show) { 58 | return ( 59 | this.close(this)} 61 | modal={true}> 62 | 63 | 64 |
65 |
66 | Delete '{api.name}'? 67 |
68 |
69 |
70 |
71 | 72 |
73 |
74 | This api will be permanently deleted. This is a destructive operation. 75 |
76 |
77 | this.setState({ nameValidation: value })} 82 | /> 83 |
84 |
85 |
86 | 87 | 88 |