├── .config
└── tsaoptions.json
├── .github
├── pull_request_template.md
└── workflows
│ └── actions-pr.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── Directory.Build.props
├── Directory.Build.targets
├── LICENSE.txt
├── README.md
├── SECURITY.md
├── SUPPORT.md
├── VSConfigFinder.Test
├── .editorconfig
├── ExtensionsTests.cs
├── UtilitiesTests.cs
└── VSConfigFinder.Test.csproj
├── VSConfigFinder.sln
├── VSConfigFinder
├── .editorconfig
├── CommandLine
│ ├── CommandLineOptions.cs
│ ├── ICommandLineOptions.cs
│ └── VSConfig.cs
├── ConsoleLogger.cs
├── Extensions.cs
├── FileSystem.cs
├── IFileSystem.cs
├── ILogger.cs
├── Program.cs
├── Utilities.cs
└── VSConfigFinder.csproj
├── build.yml
├── global.json
├── pkg
└── VSConfigFinder
│ ├── VSConfigFinder.nuspec
│ └── tools
│ └── VERIFICATION.txt
├── version.json
├── vsts-ci.yml
└── vsts-compliance.yml
/.config/tsaoptions.json:
--------------------------------------------------------------------------------
1 | {
2 | "codebaseName": "Microsoft.VSConfigFinder",
3 | "instanceUrl": "https://devdiv.visualstudio.com/defaultcollection",
4 | "projectName": "DevDiv",
5 | "areaPath": "DevDiv\\VS Setup",
6 | "iterationPath": "DevDiv",
7 | "allTools": true
8 | }
9 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## What?
2 | _Include a sentence or two about what the change is trying to accomplish_
3 |
4 | ## Why?
5 | _Include a sentence or two about why the change is needed_
6 |
7 | ## How?
8 | _Include a sentence or two about how the change achieves its goal_
9 |
10 | ## Testing?
11 | - [ ] Added unit tests
12 | - [ ] _Add any manual test scenarios_
13 |
14 | ## Screenshots (optional)
15 | _Include any screenshots if the change includes UI changes_
16 |
17 | ## Additional information (optional)
18 | _Include any additional information to help give context on the change_
19 |
--------------------------------------------------------------------------------
/.github/workflows/actions-pr.yml:
--------------------------------------------------------------------------------
1 | # Copyright (C) Microsoft Corporation. All rights reserved.
2 | # Licensed under the MIT license. See LICENSE.txt in the project root for license information.
3 |
4 | name: PR Build
5 |
6 | on: [ pull_request ]
7 |
8 | env:
9 | # Path to the project source.
10 | PROJECT_PATH: VSConfigFinder
11 |
12 | # Path to the test project source.
13 | TEST_PROJECT_PATH: VSConfigFinder.Test
14 |
15 | # Configuration type to build.
16 | BUILD_CONFIGURATION: Release
17 |
18 | jobs:
19 | build:
20 | runs-on: windows-2022
21 |
22 | steps:
23 | - name: Checkout
24 | uses: actions/checkout@v3
25 | with:
26 | fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
27 |
28 | - name: Install .NET Core SDK
29 | uses: actions/setup-dotnet@v3
30 | with:
31 | global-json-file: global.json
32 |
33 | - name: Restore dependencies
34 | run: dotnet restore
35 |
36 | - name: Build
37 | run: dotnet build --no-restore --configuration ${{ env.BUILD_CONFIGURATION }} ${{ env.PROJECT_PATH }}
38 |
39 | - name: Test
40 | run: dotnet test --verbosity normal --configuration ${{ env.BUILD_CONFIGURATION }} ${{ env.TEST_PROJECT_PATH }}
41 |
42 | - name: Publish
43 | run: dotnet publish --no-build --configuration ${{ env.BUILD_CONFIGURATION }} ${{ env.PROJECT_PATH }}
44 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | bld/
19 | [Bb]in/
20 | [Oo]bj/
21 |
22 | # Visual Studio 2015 cache/options directory
23 | .vs/
24 |
25 | # MSTest test Results
26 | [Tt]est[Rr]esult*/
27 | [Bb]uild[Ll]og.*
28 | *.coverage
29 |
30 | # NUNIT
31 | *.VisualState.xml
32 | TestResult.xml
33 |
34 | # Build Results of an ATL Project
35 | [Dd]ebugPS/
36 | [Rr]eleasePS/
37 | dlldata.c
38 |
39 | # DNX
40 | project.lock.json
41 | artifacts/
42 |
43 | *_i.c
44 | *_p.c
45 | *_i.h
46 | *.ilk
47 | *.meta
48 | *.obj
49 | *.opendb
50 | *.pch
51 | *.pdb
52 | *.pgc
53 | *.pgd
54 | *.rsp
55 | *.sbr
56 | *.tlb
57 | *.tli
58 | *.tlh
59 | *.tmp
60 | *.tmp_proj
61 | *.log
62 | *.binlog
63 | *.vspscc
64 | *.vssscc
65 | .builds
66 | *.pidb
67 | *.svclog
68 | *.scc
69 |
70 | # Chutzpah Test files
71 | _Chutzpah*
72 |
73 | # Visual C++ cache files
74 | ipch/
75 | *.aps
76 | *.ncb
77 | *.opensdf
78 | *.sdf
79 | *.cachefile
80 | *.db
81 |
82 | # Visual Studio profiler
83 | *.psess
84 | *.vsp
85 | *.vspx
86 |
87 | # TFS 2012 Local Workspace
88 | $tf/
89 |
90 | # Guidance Automation Toolkit
91 | *.gpState
92 |
93 | # ReSharper is a .NET coding add-in
94 | _ReSharper*/
95 | *.[Rr]e[Ss]harper
96 | *.DotSettings.user
97 |
98 | # JustCode is a .NET coding add-in
99 | .JustCode
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | _NCrunch_*
109 | .*crunch*.local.xml
110 |
111 | # MightyMoose
112 | *.mm.*
113 | AutoTest.Net/
114 |
115 | # Web workbench (sass)
116 | .sass-cache/
117 |
118 | # Installshield output folder
119 | [Ee]xpress/
120 |
121 | # DocProject is a documentation generator add-in
122 | DocProject/buildhelp/
123 | DocProject/Help/*.HxT
124 | DocProject/Help/*.HxC
125 | DocProject/Help/*.hhc
126 | DocProject/Help/*.hhk
127 | DocProject/Help/*.hhp
128 | DocProject/Help/Html2
129 | DocProject/Help/html
130 |
131 | # Click-Once directory
132 | publish/
133 |
134 | # Publish Web Output
135 | *.[Pp]ublish.xml
136 | *.azurePubxml
137 | ## TODO: Comment the next line if you want to checkin your
138 | ## web deploy settings but do note that will include unencrypted
139 | ## passwords
140 | #*.pubxml
141 |
142 | *.publishproj
143 |
144 | # NuGet Packages
145 | *.nupkg
146 | *.nuget.*
147 | # The packages folder can be ignored because of Package Restore
148 | **/packages/*
149 | # except build/, which is used as an MSBuild target.
150 | !**/packages/build/
151 | # Uncomment if necessary however generally it will be regenerated when needed
152 | #!**/packages/repositories.config
153 |
154 | # Windows Azure Build Output
155 | csx/
156 | *.build.csdef
157 |
158 | # Windows Store app package directory
159 | AppPackages/
160 |
161 | # Visual Studio cache files
162 | # files ending in .cache can be ignored
163 | *.[Cc]ache
164 | # but keep track of directories ending in .cache
165 | !*.[Cc]ache/
166 |
167 | # Others
168 | ClientBin/
169 | ~$*
170 | *~
171 | *.dbmdl
172 | *.dbproj.schemaview
173 | *.pfx
174 | *.publishsettings
175 | node_modules/
176 | orleans.codegen.cs
177 |
178 | # RIA/Silverlight projects
179 | Generated_Code/
180 |
181 | # Backup & report files from converting an old project file
182 | # to a newer Visual Studio version. Backup files are not needed,
183 | # because we have git ;-)
184 | _UpgradeReport_Files/
185 | Backup*/
186 | UpgradeLog*.XML
187 | UpgradeLog*.htm
188 |
189 | # SQL Server files
190 | *.mdf
191 | *.ldf
192 |
193 | # Business Intelligence projects
194 | *.rdl.data
195 | *.bim.layout
196 | *.bim_*.settings
197 |
198 | # Microsoft Fakes
199 | FakesAssemblies/
200 |
201 | # Node.js Tools for Visual Studio
202 | .ntvs_analysis.dat
203 |
204 | # Visual Studio 6 build log
205 | *.plg
206 |
207 | # Visual Studio 6 workspace options file
208 | *.opt
209 | launchSettings.json
210 |
211 | # LightSwitch generated files
212 | GeneratedArtifacts/
213 | _Pvt_Extensions/
214 | ModelManifest.xml
215 |
216 | # vcpkg generated files
217 | vcpkg_installed/
218 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 |
7 | true
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 | true
9 | Microsoft400
10 |
11 |
12 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
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
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Visual Studio] VSConfig Finder
2 |
3 | 
4 | [](https://github.com/microsoft/VSConfigFinder/releases/latest)
5 | [](https://github.com/microsoft/VSConfigFinder/releases)
6 |
7 | When you want to set up Visual Studio from a new environment, `.vsconfig` files can be very useful as they are easy to be created from your [existing installations](https://learn.microsoft.com/en-us/visualstudio/install/import-export-installation-configurations?view=vs-2022) or from a [working solution](https://devblogs.microsoft.com/setup/configure-visual-studio-across-your-organization-with-vsconfig/). However, one existing problem with the `.vsconfig` usage is that the Visual Studio Installer supports importing one `.vsconfig` file at a time, so if you have multiple `.vsconfig`s throughout your solution (e.g. you have a monorepo that is consisted of multiple projects) and you want to apply them while setting up your pipeline, you would have to run an installer operation as many times as you'd want to use the different `.vsconfig`s. One way to get around this problem is to generate a single `.vsconfig` yourself that you put on the root of the solution, but this approach still has its own issues: For example, if you're only interested in a subset of the solution, you'll install far more components than the ones you need, resulting in a longer install and subsequent update time.
8 |
9 | _VSConfigFinder_ is designed to be a redistributable, single-file executable that can be used in build or deployment scripts to use multiple `.vsconfig`s that exist throughout the solution without having to go through multiple installer operations by recursively finding nested `.vsconfig` files and merging them into a single output file, or an installer command line argument, depending on the customer requirement.
10 |
11 | _VSConfigFinder_ is a simple tool and will not be shipped with the Visual Studio Installer, so please feel free to consume the package based on your need and use it for your own deployment setup.
12 |
13 | ## Example
14 |
15 | Imagine that you have a solution or a repository with the folder structure as below:
16 |
17 | ```
18 | root
19 | - folderA
20 | - folderB
21 | - .vsconfig (packageE)
22 | - folderC
23 | - someProject
24 | - .vsconfig (packageA, packageB)
25 | - folderD
26 | - folderE
27 | - .vsconfig (pacakgeC)
28 | - folderF
29 | - .vsconfig (packageD)
30 | ```
31 |
32 | If you want to pass in all the components that are needed to build & run `folderC`, you could run the tool with the following parameters:
33 |
34 | `VSConfigFinder.exe --folderpath root\folderC`
35 |
36 | This will generate the following command as a console output that you can simply pass into the installer.
37 |
38 | `--add packageA --add packageB --add packageC --add packageD`
39 |
40 | Remember to add your own verb (e.g. `install` or `modify`) in conjunction with the tool output.
41 |
42 | ## Multi-Root Folders Support
43 |
44 | Say if you want to do something similar to the example above, but you want everything under `folderB` AND `folderC`. You cannot pass in one or the other, because the two do not share a common folder (if you pass in the `root`, `folderA` will also be included). Instead, you can simply pass in the topmost folders as a list to achieve your goal.
45 |
46 | `VSConfigFinder.exe --folderpath root\folderC root\folderB`
47 |
48 | This will generate the following command as a console output that you can simply pass into the installer.
49 |
50 | `--add packageA --add packageB --add packageC --add packageD --add packageE`
51 |
52 | Again, remember to add your own verb (e.g. `install` or `modify`) in conjunction with the tool output.
53 |
54 | ## Alternate Example
55 |
56 | Alternatively, you can pass in additional parameters provided by the tool to get the merged `.vsconfig` as a single file:
57 |
58 | `VSConfigFinder.exe --folderpath root\folderC --createfile --configoutputpath c:\somefolder`
59 |
60 | This will generate an alternate single `.vsconfig` file with all the needed components in the specified `configOutputPath`. If you don't specify a `configOutputPath`, the output directory will default to the current directory.
61 |
62 | Note that if you choose to use `--createfile`, the Visual Studio Installer arguments will no longer be output to the console.
63 |
64 | ## Contributing
65 |
66 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
67 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
68 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
69 |
70 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide
71 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
72 | provided by the bot. You will only need to do this once across all repos using our CLA.
73 |
74 | ## License
75 |
76 | This project is licensed under the [MIT license](LICENSE.txt).
77 |
78 | ## Code of Conduct
79 |
80 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
81 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
82 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
83 |
84 | ## Trademarks
85 |
86 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
87 | trademarks or logos is subject to and must follow
88 | [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
89 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
90 | Any use of third-party trademarks or logos are subject to those third-party's policies.
91 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # TODO: The maintainer of this repo has not yet edited this file
2 |
3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project?
4 |
5 | - **No CSS support:** Fill out this template with information about how to file issues and get help.
6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps.
7 | - **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide.
8 |
9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.*
10 |
11 | # Support
12 |
13 | ## How to file issues and get help
14 |
15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing
16 | issues before filing new issues to avoid duplicates. For new issues, file your bug or
17 | feature request as a new Issue.
18 |
19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE
20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER
21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**.
22 |
23 | ## Microsoft Support Policy
24 |
25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above.
26 |
--------------------------------------------------------------------------------
/VSConfigFinder.Test/.editorconfig:
--------------------------------------------------------------------------------
1 | file_header_template = \nCopyright (C) Microsoft Corporation. All rights reserved.\nLicensed under the MIT license. See LICENSE.txt in the project root for license information.\n
2 |
3 | # All files
4 | [*]
5 | indent_style = space
6 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
7 | tab_width = 4
8 | indent_size = 4
9 | end_of_line = crlf
10 | csharp_indent_labels = one_less_than_current
11 | dotnet_style_coalesce_expression = true:suggestion
12 | dotnet_style_null_propagation = true:suggestion
13 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
14 | dotnet_style_prefer_auto_properties = true:silent
15 | dotnet_style_object_initializer = true:suggestion
16 | dotnet_style_collection_initializer = true:suggestion
17 | dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
18 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
19 | csharp_using_directive_placement = inside_namespace:error
20 | csharp_prefer_simple_using_statement = true:suggestion
21 | csharp_prefer_braces = true:silent
22 | csharp_style_namespace_declarations = block_scoped:silent
23 | csharp_style_prefer_method_group_conversion = true:silent
24 | csharp_style_prefer_top_level_statements = true:silent
25 | csharp_style_expression_bodied_methods = false:silent
26 | csharp_style_expression_bodied_constructors = false:silent
27 | csharp_style_expression_bodied_operators = false:silent
28 | csharp_style_expression_bodied_properties = true:silent
29 | csharp_style_expression_bodied_indexers = true:silent
30 | csharp_style_expression_bodied_accessors = true:silent
31 | csharp_style_expression_bodied_lambdas = true:silent
32 | csharp_style_expression_bodied_local_functions = false:silent
33 | csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
34 | csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
35 | csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
36 | csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent
37 | csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent
38 | csharp_new_line_before_open_brace = all
39 | csharp_style_throw_expression = true:suggestion
40 | csharp_prefer_simple_default_expression = true:suggestion
41 | csharp_style_prefer_null_check_over_type_check = true:suggestion
42 | csharp_style_prefer_local_over_anonymous_function = true:suggestion
43 | csharp_style_prefer_index_operator = true:suggestion
44 | csharp_style_prefer_range_operator = true:suggestion
45 | csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
46 | csharp_style_prefer_tuple_swap = true:suggestion
47 | csharp_style_prefer_utf8_string_literals = true:suggestion
48 | csharp_style_inlined_variable_declaration = true:suggestion
49 | csharp_style_deconstructed_variable_declaration = true:suggestion
50 | csharp_style_unused_value_assignment_preference = discard_variable:suggestion
51 | csharp_style_unused_value_expression_statement_preference = discard_variable:silent
52 | csharp_prefer_static_local_function = true:suggestion
53 | csharp_style_prefer_readonly_struct = true:suggestion
54 | csharp_style_conditional_delegate_call = true:suggestion
55 | csharp_style_prefer_switch_expression = true:suggestion
56 | csharp_style_prefer_pattern_matching = true:silent
57 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
58 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
59 | csharp_style_prefer_not_pattern = true:suggestion
60 | csharp_style_prefer_extended_property_pattern = true:suggestion
61 | csharp_style_var_for_built_in_types = true:silent
62 | csharp_style_var_when_type_is_apparent = true:silent
63 | csharp_style_var_elsewhere = true:silent
64 |
65 | # Xml files
66 | [*.xml]
67 | indent_size = 2
68 |
69 | [*.{cs,vb}]
70 | #### Naming styles ####
71 |
72 | # Naming rules
73 |
74 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
75 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
76 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
77 |
78 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
79 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
80 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
81 |
82 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
83 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
84 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
85 |
86 | # Symbol specifications
87 |
88 | dotnet_naming_symbols.interface.applicable_kinds = interface
89 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
90 | dotnet_naming_symbols.interface.required_modifiers =
91 |
92 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
93 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
94 | dotnet_naming_symbols.types.required_modifiers =
95 |
96 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
97 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
98 | dotnet_naming_symbols.non_field_members.required_modifiers =
99 |
100 | # Naming styles
101 |
102 | dotnet_naming_style.begins_with_i.required_prefix = I
103 | dotnet_naming_style.begins_with_i.required_suffix =
104 | dotnet_naming_style.begins_with_i.word_separator =
105 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
106 |
107 | dotnet_naming_style.pascal_case.required_prefix =
108 | dotnet_naming_style.pascal_case.required_suffix =
109 | dotnet_naming_style.pascal_case.word_separator =
110 | dotnet_naming_style.pascal_case.capitalization = pascal_case
111 |
112 | dotnet_naming_style.pascal_case.required_prefix =
113 | dotnet_naming_style.pascal_case.required_suffix =
114 | dotnet_naming_style.pascal_case.word_separator =
115 | dotnet_naming_style.pascal_case.capitalization = pascal_case
116 | dotnet_style_allow_multiple_blank_lines_experimental = true:silent
117 | dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
118 |
119 | # Diagnostics
120 |
121 | # CS8602: Dereference of a possibly null reference.
122 | dotnet_diagnostic.CS8602.severity = error
123 | # CS8603: Possible null reference return.
124 | dotnet_diagnostic.CS8603.severity = error
125 | dotnet_style_namespace_match_folder = true:suggestion
126 | dotnet_style_prefer_conditional_expression_over_return = true:silent
127 | dotnet_style_explicit_tuple_names = true:suggestion
128 | dotnet_style_prefer_inferred_tuple_names = true:suggestion
129 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
130 | dotnet_style_prefer_compound_assignment = true:suggestion
131 | dotnet_style_prefer_simplified_interpolation = true:suggestion
132 | dotnet_style_readonly_field = true:suggestion
133 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent
134 | dotnet_style_predefined_type_for_member_access = true:silent
135 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
136 | dotnet_code_quality_unused_parameters = all:warning
137 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
138 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
139 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
140 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
141 | dotnet_style_qualification_for_field = false:silent
142 | dotnet_style_qualification_for_property = false:silent
143 | dotnet_style_qualification_for_method = false:silent
144 | dotnet_style_qualification_for_event = false:silent
--------------------------------------------------------------------------------
/VSConfigFinder.Test/ExtensionsTests.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder.Test
7 | {
8 | using Moq;
9 | using Xunit;
10 |
11 | public class ExtensionsTests
12 | {
13 | [Fact]
14 | public void GetFileSystemEntries_MultiplePaths_ReturnSet()
15 | {
16 | var path1 = "C:\\path1";
17 | var subpath1 = Path.Combine(path1, "subpath1", ".vsconfig");
18 | var subpath2 = Path.Combine(path1, "subpath2", "something.vsconfig");
19 | var path2 = "C:\\path2";
20 | var subpath3 = Path.Combine(path2, "subpath3", ".vsconfig");
21 | var subpath4 = Path.Combine(path2, "subpath4", "something.vsconfig");
22 | var path3 = path2;
23 | var subpath5 = subpath3;
24 | var subpath6 = subpath4;
25 |
26 | var fileSystem = new Mock();
27 | fileSystem.Setup(x => x.GetFileSystemEntries(path1, "*.vsconfig", true)).Returns(new[] { subpath1, subpath2 });
28 | fileSystem.Setup(x => x.GetFileSystemEntries(path2, "*.vsconfig", true)).Returns(new[] { subpath3, subpath4 });
29 | fileSystem.Setup(x => x.GetFileSystemEntries(path3, "*.vsconfig", true)).Returns(new[] { subpath5, subpath6 });
30 |
31 | var paths = new[] { path1, path2, path3 };
32 |
33 | var result = Extensions.GetFileSystemEntries(fileSystem.Object, paths, "*.vsconfig", recursive: true);
34 |
35 | Assert.Equal(4, result.Count());
36 | Assert.Contains(subpath1, result);
37 | Assert.Contains(subpath2, result);
38 | Assert.Contains(subpath3, result);
39 | Assert.Contains(subpath4, result);
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/VSConfigFinder.Test/UtilitiesTests.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder.Test
7 | {
8 | using Moq;
9 | using System.Text;
10 | using Xunit;
11 |
12 | public class UtilitiesTests
13 | {
14 | const string VSConfig = ".vsconfig";
15 |
16 | [Fact]
17 | public void ValidateIsNotNullOrEmpty_NullOrEmpty_String_Throws_AppropriateException()
18 | {
19 | string? nullStr = null;
20 | Assert.Throws(() => Utilities.ValidateIsNotNullOrEmpty(nullStr!, nameof(nullStr)));
21 |
22 | var emptyStr = string.Empty;
23 | Assert.Throws(() => Utilities.ValidateIsNotNullOrEmpty(emptyStr, nameof(emptyStr)));
24 | }
25 |
26 | [Fact]
27 | public void ValidateIsNotNullOrEmpty_NotNullOrEmpty_String_Succeeds()
28 | {
29 | var str = "some string";
30 | Utilities.ValidateIsNotNullOrEmpty(str, nameof(str));
31 | }
32 |
33 | [Theory]
34 | [InlineData(true)]
35 | [InlineData(false)]
36 | public void CreateOutput_Creates_FileOrArguments_With_Expected_String(bool createFile)
37 | {
38 | var fileSystem = new Mock();
39 | var logger = new Mock();
40 |
41 | var finalConfig = new VSConfig
42 | {
43 | Version = new Version("1.0"),
44 | Components = new[]
45 | {
46 | "Microsoft.VisualStudio.Component.NuGet",
47 | "Microsoft.VisualStudio.Component.Roslyn.Compiler",
48 | "Microsoft.Component.MSBuild",
49 | "Microsoft.NetCore.Component.Runtime.6.0"
50 | },
51 | };
52 |
53 | var jsonString = """
54 | {
55 | "Version": "1.0",
56 | "Components": [
57 | "Microsoft.VisualStudio.Component.NuGet",
58 | "Microsoft.VisualStudio.Component.Roslyn.Compiler",
59 | "Microsoft.Component.MSBuild",
60 | "Microsoft.NetCore.Component.Runtime.6.0"
61 | ]
62 | }
63 | """;
64 |
65 | var options = new CommandLineOptions
66 | {
67 | FolderPath = new[] { "C:\\input" },
68 | CreateFile = createFile,
69 | ConfigOutputPath = "C:\\output",
70 | };
71 |
72 | Utilities.CreateOutput(fileSystem.Object, logger.Object, finalConfig, options);
73 |
74 | if (createFile)
75 | {
76 | var outputPath = Path.Combine(options.ConfigOutputPath, VSConfig);
77 | fileSystem.Verify(x => x.WriteAllText(outputPath, jsonString));
78 | }
79 | else
80 | {
81 | var addArguments = "--add Microsoft.VisualStudio.Component.NuGet --add Microsoft.VisualStudio.Component.Roslyn.Compiler --add Microsoft.Component.MSBuild --add Microsoft.NetCore.Component.Runtime.6.0";
82 | logger.Verify(x => x.Log(addArguments));
83 | }
84 | }
85 |
86 | [Fact]
87 | public void ReadComponents_Reads_AllNestedDirectories_And_OutputsAllComponents()
88 | {
89 | /*
90 | * folder structure:
91 | * pathA
92 | * - .vsconfig
93 | * - pathB
94 | * - .vsconfig
95 | */
96 |
97 | var fileSystem = new Mock();
98 |
99 | var options = new CommandLineOptions
100 | {
101 | FolderPath = new[] { "C:\\pathA" },
102 | ConfigOutputPath = "C:\\output",
103 | };
104 |
105 | // pathA
106 | var pathA = "C:\\pathA";
107 | var pathAConfigFile = Path.Combine(pathA, VSConfig);
108 |
109 | var pathAConfig = """
110 | {
111 | "Version": "1.0",
112 | "Components": [
113 | "Microsoft.VisualStudio.Component.NuGet",
114 | "Microsoft.Component.MSBuild",
115 | ]
116 | }
117 | """;
118 | var pathAReader = new MemoryStream(Encoding.UTF8.GetBytes(pathAConfig));
119 |
120 | // pathB
121 | var pathB = Path.Combine(pathA, "pathB");
122 | var pathBConfigFile = Path.Combine(pathB, VSConfig);
123 |
124 | var pathBConfig = """
125 | {
126 | "Version": "1.0",
127 | "Components": [
128 | "Microsoft.VisualStudio.Component.NuGet",
129 | "Microsoft.VisualStudio.Component.Roslyn.Compiler",
130 | ]
131 | }
132 | """;
133 | var pathBReader = new MemoryStream(Encoding.UTF8.GetBytes(pathBConfig));
134 |
135 | fileSystem.Setup(x => x.GetFileSystemEntries("C:\\pathA", "*" + VSConfig, true)).Returns(new[] { pathAConfigFile, pathBConfigFile });
136 |
137 | fileSystem.Setup(x => x.OpenFile(pathAConfigFile)).Returns(pathAReader);
138 | fileSystem.Setup(x => x.OpenFile(pathBConfigFile)).Returns(pathBReader);
139 |
140 | var components = Utilities.ReadComponents(fileSystem.Object, options);
141 | Assert.Equal(3, components.Length);
142 | Assert.Collection(
143 | components,
144 | x => Assert.Equal("Microsoft.VisualStudio.Component.NuGet", x),
145 | x => Assert.Equal("Microsoft.Component.MSBuild", x),
146 | x => Assert.Equal("Microsoft.VisualStudio.Component.Roslyn.Compiler", x));
147 | }
148 | }
149 | }
--------------------------------------------------------------------------------
/VSConfigFinder.Test/VSConfigFinder.Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net7.0
5 | enable
6 | enable
7 |
8 | false
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | runtime; build; native; contentfiles; analyzers; buildtransitive
17 | all
18 |
19 |
20 | runtime; build; native; contentfiles; analyzers; buildtransitive
21 | all
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/VSConfigFinder.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.6.33405.23
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VSConfigFinder", "VSConfigFinder\VSConfigFinder.csproj", "{0F9FDAD0-EF20-4EAE-B37E-2E49975CFED1}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7E2E70F6-1FBA-48EA-920A-9B4032D280C3}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSConfigFinder.Test", "VSConfigFinder.Test\VSConfigFinder.Test.csproj", "{A146B74D-CC67-4ABC-92E6-346784A7D115}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {0F9FDAD0-EF20-4EAE-B37E-2E49975CFED1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {0F9FDAD0-EF20-4EAE-B37E-2E49975CFED1}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {0F9FDAD0-EF20-4EAE-B37E-2E49975CFED1}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {0F9FDAD0-EF20-4EAE-B37E-2E49975CFED1}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {A146B74D-CC67-4ABC-92E6-346784A7D115}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {A146B74D-CC67-4ABC-92E6-346784A7D115}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {A146B74D-CC67-4ABC-92E6-346784A7D115}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {A146B74D-CC67-4ABC-92E6-346784A7D115}.Release|Any CPU.Build.0 = Release|Any CPU
26 | EndGlobalSection
27 | GlobalSection(SolutionProperties) = preSolution
28 | HideSolutionNode = FALSE
29 | EndGlobalSection
30 | GlobalSection(ExtensibilityGlobals) = postSolution
31 | SolutionGuid = {B8A58883-E63D-4E5D-8797-92039A0EA333}
32 | EndGlobalSection
33 | EndGlobal
34 |
--------------------------------------------------------------------------------
/VSConfigFinder/.editorconfig:
--------------------------------------------------------------------------------
1 | file_header_template = \nCopyright (C) Microsoft Corporation. All rights reserved.\nLicensed under the MIT license. See LICENSE.txt in the project root for license information.\n
2 |
3 | # All files
4 | [*]
5 | indent_style = space
6 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
7 | tab_width = 4
8 | indent_size = 4
9 | end_of_line = crlf
10 | csharp_indent_labels = one_less_than_current
11 | dotnet_style_coalesce_expression = true:suggestion
12 | dotnet_style_null_propagation = true:suggestion
13 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
14 | dotnet_style_prefer_auto_properties = true:silent
15 | dotnet_style_object_initializer = true:suggestion
16 | dotnet_style_collection_initializer = true:suggestion
17 | dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
18 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
19 | csharp_using_directive_placement = inside_namespace:error
20 | csharp_prefer_simple_using_statement = true:suggestion
21 | csharp_prefer_braces = true:silent
22 | csharp_style_namespace_declarations = block_scoped:silent
23 | csharp_style_prefer_method_group_conversion = true:silent
24 | csharp_style_prefer_top_level_statements = true:silent
25 | csharp_style_expression_bodied_methods = false:silent
26 | csharp_style_expression_bodied_constructors = false:silent
27 | csharp_style_expression_bodied_operators = false:silent
28 | csharp_style_expression_bodied_properties = true:silent
29 | csharp_style_expression_bodied_indexers = true:silent
30 | csharp_style_expression_bodied_accessors = true:silent
31 | csharp_style_expression_bodied_lambdas = true:silent
32 | csharp_style_expression_bodied_local_functions = false:silent
33 | csharp_style_allow_embedded_statements_on_same_line_experimental = true:silent
34 | csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true:silent
35 | csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:silent
36 | csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true:silent
37 | csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:silent
38 | csharp_new_line_before_open_brace = all
39 | csharp_style_throw_expression = true:suggestion
40 | csharp_prefer_simple_default_expression = true:suggestion
41 | csharp_style_prefer_null_check_over_type_check = true:suggestion
42 | csharp_style_prefer_local_over_anonymous_function = true:suggestion
43 | csharp_style_prefer_index_operator = true:suggestion
44 | csharp_style_prefer_range_operator = true:suggestion
45 | csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
46 | csharp_style_prefer_tuple_swap = true:suggestion
47 | csharp_style_prefer_utf8_string_literals = true:suggestion
48 | csharp_style_inlined_variable_declaration = true:suggestion
49 | csharp_style_deconstructed_variable_declaration = true:suggestion
50 | csharp_style_unused_value_assignment_preference = discard_variable:suggestion
51 | csharp_style_unused_value_expression_statement_preference = discard_variable:silent
52 | csharp_prefer_static_local_function = true:suggestion
53 | csharp_style_prefer_readonly_struct = true:suggestion
54 | csharp_style_conditional_delegate_call = true:suggestion
55 | csharp_style_prefer_switch_expression = true:suggestion
56 | csharp_style_prefer_pattern_matching = true:silent
57 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
58 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
59 | csharp_style_prefer_not_pattern = true:suggestion
60 | csharp_style_prefer_extended_property_pattern = true:suggestion
61 | csharp_style_var_for_built_in_types = true:silent
62 | csharp_style_var_when_type_is_apparent = true:silent
63 | csharp_style_var_elsewhere = true:silent
64 |
65 | # Xml files
66 | [*.xml]
67 | indent_size = 2
68 |
69 | [*.{cs,vb}]
70 | #### Naming styles ####
71 |
72 | # Naming rules
73 |
74 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
75 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
76 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
77 |
78 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
79 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
80 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
81 |
82 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
83 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
84 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
85 |
86 | # Symbol specifications
87 |
88 | dotnet_naming_symbols.interface.applicable_kinds = interface
89 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
90 | dotnet_naming_symbols.interface.required_modifiers =
91 |
92 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
93 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
94 | dotnet_naming_symbols.types.required_modifiers =
95 |
96 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
97 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
98 | dotnet_naming_symbols.non_field_members.required_modifiers =
99 |
100 | # Naming styles
101 |
102 | dotnet_naming_style.begins_with_i.required_prefix = I
103 | dotnet_naming_style.begins_with_i.required_suffix =
104 | dotnet_naming_style.begins_with_i.word_separator =
105 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
106 |
107 | dotnet_naming_style.pascal_case.required_prefix =
108 | dotnet_naming_style.pascal_case.required_suffix =
109 | dotnet_naming_style.pascal_case.word_separator =
110 | dotnet_naming_style.pascal_case.capitalization = pascal_case
111 |
112 | dotnet_naming_style.pascal_case.required_prefix =
113 | dotnet_naming_style.pascal_case.required_suffix =
114 | dotnet_naming_style.pascal_case.word_separator =
115 | dotnet_naming_style.pascal_case.capitalization = pascal_case
116 | dotnet_style_allow_multiple_blank_lines_experimental = true:silent
117 | dotnet_style_allow_statement_immediately_after_block_experimental = true:silent
118 |
119 | # Diagnostics
120 |
121 | # CS8602: Dereference of a possibly null reference.
122 | dotnet_diagnostic.CS8602.severity = error
123 | # CS8603: Possible null reference return.
124 | dotnet_diagnostic.CS8603.severity = error
125 | dotnet_style_namespace_match_folder = true:suggestion
126 | dotnet_style_prefer_conditional_expression_over_return = true:silent
127 | dotnet_style_explicit_tuple_names = true:suggestion
128 | dotnet_style_prefer_inferred_tuple_names = true:suggestion
129 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
130 | dotnet_style_prefer_compound_assignment = true:suggestion
131 | dotnet_style_prefer_simplified_interpolation = true:suggestion
132 | dotnet_style_readonly_field = true:suggestion
133 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent
134 | dotnet_style_predefined_type_for_member_access = true:silent
135 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
136 | dotnet_code_quality_unused_parameters = all:warning
137 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
138 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
139 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
140 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
141 | dotnet_style_qualification_for_field = false:silent
142 | dotnet_style_qualification_for_property = false:silent
143 | dotnet_style_qualification_for_method = false:silent
144 | dotnet_style_qualification_for_event = false:silent
--------------------------------------------------------------------------------
/VSConfigFinder/CommandLine/CommandLineOptions.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | using CommandLine;
9 |
10 | ///
11 | public class CommandLineOptions : ICommandLineOptions
12 | {
13 | ///
14 | [Option("folderpath", Required = true, HelpText = "The source folder path to use as the root. The search will start from the root towards the bottom.")]
15 | public IEnumerable? FolderPath { get; set; }
16 |
17 | ///
18 | [Option("createfile", Required = false, Default = false, HelpText = "(Default: false) Bool flag that indicates whether the output gets created as a consolidated .vsconfig file instead of the Visual Studio Installer setup command line arguments.\n" +
19 | "If --createFile is passed in, --configOutputPath can also be passed in to indicate the output directory.")]
20 | public bool CreateFile { get; set; }
21 |
22 | ///
23 | [Option("configoutputpath", Required = false, HelpText = "The optional folder path to use if --createFile is passed in. If empty or null, uses the current directory as the output path.\n" +
24 | "This can only be used in conjunction with --createFile. If passed in without --createFile, the parameter will be ignored.")]
25 | public string? ConfigOutputPath { get; set; }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/VSConfigFinder/CommandLine/ICommandLineOptions.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | ///
9 | /// The interface for the command line options.
10 | ///
11 | public interface ICommandLineOptions
12 | {
13 | ///
14 | /// Gets or sets the folder paths to be used as the root (starting point) of the search.
15 | ///
16 | IEnumerable? FolderPath { get; set; }
17 |
18 | ///
19 | /// Gets or sets the value indicating whether the output gets created as a consolidated .vsconfig file instead of the Visual Studio Installer setup command line arguments.
20 | /// If --createFile is passed in, can also be passed in to indicate the output directory.folder path to output the consolidated .vsconfig instead of the command line arguments.
21 | ///
22 | bool CreateFile { get; set; }
23 |
24 | ///
25 | /// Gets or sets the optional folder path to use if --createFile is passed in.
26 | /// If empty or null, uses the current directory as the output path.
27 | /// This can only be used in conjunction with --createFile. If passed in without --createFile, the parameter will be ignored.
28 | ///
29 | string? ConfigOutputPath { get; set; }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/VSConfigFinder/CommandLine/VSConfig.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | using System;
9 |
10 | ///
11 | /// The class object that defines a .vsconfig file.
12 | ///
13 | public class VSConfig
14 | {
15 | ///
16 | /// Gets or sets the version of the .vsconfig file.
17 | ///
18 | public Version? Version { get; set; }
19 |
20 | ///
21 | /// Gets or sets the list of component ids.
22 | ///
23 | public string[]? Components { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/VSConfigFinder/ConsoleLogger.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | using System;
9 |
10 | ///
11 | internal class ConsoleLogger : ILogger
12 | {
13 | ///
14 | public void Log(string message) => Console.WriteLine(message);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/VSConfigFinder/Extensions.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | using System;
9 | using System.Collections.Generic;
10 |
11 | ///
12 | /// Extensions class for the tool.
13 | ///
14 | public static class Extensions
15 | {
16 | ///
17 | /// The extension method to get entries from multiple paths.
18 | ///
19 | /// The .
20 | /// The list of top-level paths.
21 | /// Pattern to match for file names. To match anything and everything, specify '*'
22 | /// Optional: recursively search sub directories
23 | /// A set of path to files that match the pattern
24 | public static IEnumerable GetFileSystemEntries(this IFileSystem fileSystem, IEnumerable paths, string pattern, bool recursive = false)
25 | {
26 | Utilities.IsNotNull(paths, nameof(paths));
27 | Utilities.ValidateIsNotNullOrEmpty(pattern, nameof(pattern));
28 |
29 | var result = new HashSet(StringComparer.OrdinalIgnoreCase);
30 |
31 | foreach (var path in paths)
32 | {
33 | result.UnionWith(fileSystem.GetFileSystemEntries(path, pattern, recursive));
34 | }
35 |
36 | return result;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/VSConfigFinder/FileSystem.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | using System.IO;
9 |
10 | ///
11 | public class FileSystem : IFileSystem
12 | {
13 | ///
14 | public IEnumerable GetFileSystemEntries(string path, string pattern, bool recursive = false)
15 | {
16 | Utilities.ValidateIsNotNullOrEmpty(path, nameof(path));
17 | Utilities.ValidateIsNotNullOrEmpty(pattern, nameof(pattern));
18 |
19 | return Directory.GetFileSystemEntries(path, pattern, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
20 | }
21 |
22 | ///
23 | public Stream OpenFile(string path)
24 | {
25 | Utilities.ValidateIsNotNullOrEmpty(path, nameof(Path));
26 |
27 | return File.OpenRead(path);
28 | }
29 |
30 | ///
31 | public void WriteAllText(string path, string data)
32 | {
33 | Utilities.ValidateIsNotNullOrEmpty(path, nameof(Path));
34 |
35 | File.WriteAllText(path, data);
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/VSConfigFinder/IFileSystem.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | ///
9 | /// The interface for the .
10 | ///
11 | public interface IFileSystem
12 | {
13 | ///
14 | /// Get files and directories within directory.
15 | ///
16 | /// Directory path to search for.
17 | /// Pattern to match for file names. To match anything and everything, specify '*'
18 | /// Optional: recursively search sub directories
19 | /// Array of path to files that match the pattern within the directory.
20 | /// is empty.
21 | /// is null.
22 | public IEnumerable GetFileSystemEntries(string path, string pattern, bool recursive = false);
23 |
24 | ///
25 | /// Opens a file for reading.
26 | ///
27 | /// The path to a file to open.
28 | /// A stream of the opened file.
29 | /// is empty.
30 | /// is null.
31 | public Stream OpenFile(string path);
32 |
33 | ///
34 | /// Writes all text in a path.
35 | ///
36 | /// The path to a file to write.
37 | /// The string data to write.
38 | /// is empty.
39 | /// is null.
40 | public void WriteAllText(string path, string data);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/VSConfigFinder/ILogger.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | ///
9 | /// The interface to log user messages.
10 | ///
11 | public interface ILogger
12 | {
13 | ///
14 | /// Log the message.
15 | ///
16 | /// The message to log.
17 | public void Log(string message);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/VSConfigFinder/Program.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | using CommandLine;
9 | using System.IO;
10 |
11 | ///
12 | /// class for the .vsconfig finder tool.
13 | ///
14 | public class Program
15 | {
16 | ///
17 | /// Main entry point of the tool.
18 | ///
19 | /// The program arguments
20 | public static void Main(string[] args)
21 | {
22 | var parser = new Parser(with =>
23 | {
24 | with.CaseSensitive = false;
25 | });
26 |
27 | parser.ParseArguments(args)
28 | .WithParsed(Run)
29 | .WithNotParsed(HandleParseError);
30 | }
31 |
32 | private static void Run(CommandLineOptions options)
33 | {
34 | var fileSystem = new FileSystem();
35 | var logger = new ConsoleLogger();
36 |
37 | ResolveCommandLineOptions(options);
38 |
39 | var finalConfig = new VSConfig()
40 | {
41 | // This is the new final .vsconfig, so version 1.0 is used.
42 | Version = new Version("1.0"),
43 | Components = Utilities.ReadComponents(fileSystem, options),
44 | };
45 |
46 | Utilities.CreateOutput(fileSystem, logger, finalConfig, options);
47 | }
48 |
49 | private static void ResolveCommandLineOptions(CommandLineOptions options)
50 | {
51 | if (options.CreateFile)
52 | {
53 | options.ConfigOutputPath ??= Directory.GetCurrentDirectory();
54 | }
55 | }
56 |
57 | private static void HandleParseError(IEnumerable errors)
58 | {
59 | Console.WriteLine("Please make sure that you have provided the correct arguments. Try --help to see all the available arguments and explanations.");
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/VSConfigFinder/Utilities.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (C) Microsoft Corporation. All rights reserved.
3 | // Licensed under the MIT license. See LICENSE.txt in the project root for license information.
4 | //
5 |
6 | namespace VSConfigFinder
7 | {
8 | using System.Diagnostics.CodeAnalysis;
9 | using System.Text;
10 | using System.Text.Json;
11 |
12 | ///
13 | /// Utilities class for the tool.
14 | ///
15 | public class Utilities
16 | {
17 | private static readonly string ConfigExtension = ".vsconfig";
18 | private static readonly string Add = "--add";
19 |
20 | ///
21 | /// Validate whether the parameter is null or empty.
22 | ///
23 | /// The parameter.
24 | /// The nameof(parameter).
25 | public static void ValidateIsNotNullOrEmpty([NotNull] string s, string paramName)
26 | {
27 | IsNotNull(s, paramName);
28 | IsNotEmpty(s, paramName);
29 | }
30 |
31 | ///
32 | /// Validate whether the parameter is null.
33 | ///
34 | /// The parameter object.
35 | /// The nameof(parameter).
36 | /// is null.
37 | public static void IsNotNull([NotNull] object o, string paramName)
38 | {
39 | if (o is null)
40 | {
41 | throw new ArgumentNullException(paramName);
42 | }
43 | }
44 |
45 | ///
46 | /// Validate whether the parameter is empty.
47 | ///
48 | /// The string parameter object.
49 | /// The nameof(parameter).
50 | /// is empty.
51 | public static void IsNotEmpty([NotNull] string s, string paramName)
52 | {
53 | if (s == string.Empty)
54 | {
55 | throw new ArgumentException("The string is empty.", paramName);
56 | }
57 | }
58 |
59 | ///
60 | /// Create an output from the final and given .
61 | ///
62 | /// The .
63 | /// The .
64 | /// The final to export.
65 | /// The command line options.
66 | public static void CreateOutput(IFileSystem fileSystem, ILogger logger, VSConfig finalConfig, CommandLineOptions options)
67 | {
68 | if (options.CreateFile)
69 | {
70 | // Create a file
71 | var serializerOptions = new JsonSerializerOptions { WriteIndented = true };
72 | var jsonString = JsonSerializer.Serialize(finalConfig, serializerOptions);
73 | var outputPath = Path.Combine(options.ConfigOutputPath!, ConfigExtension);
74 |
75 | fileSystem.WriteAllText(outputPath, jsonString);
76 | logger.Log($"Successfully created the final .vsconfig at {outputPath}");
77 | }
78 | else
79 | {
80 | // output to a command line
81 | var output = CreateCommandLineOutput(finalConfig);
82 | logger.Log(output);
83 | }
84 | }
85 |
86 | ///
87 | /// Read all the components in the nested .vsconfigs recursively, starting from the given path.
88 | ///
89 | /// The .
90 | /// The command line options.
91 | ///
92 | public static string[] ReadComponents(IFileSystem fileSystem, CommandLineOptions options)
93 | {
94 | var pathsToVsConfigs = fileSystem.GetFileSystemEntries(options.FolderPath, "*" + ConfigExtension, recursive: true);
95 |
96 | var componentsSet = new HashSet(StringComparer.OrdinalIgnoreCase);
97 | var serializerOptions = new JsonSerializerOptions
98 | {
99 | PropertyNameCaseInsensitive = true,
100 | AllowTrailingCommas = true,
101 | };
102 |
103 | foreach (var path in pathsToVsConfigs)
104 | {
105 | string[]? components;
106 | using (var stream = fileSystem.OpenFile(path))
107 | {
108 | components = JsonSerializer.Deserialize(stream, serializerOptions)?.Components;
109 | }
110 |
111 | if (components is not null)
112 | {
113 | componentsSet.UnionWith(components);
114 | }
115 | };
116 |
117 | return componentsSet.ToArray();
118 | }
119 |
120 | private static string CreateCommandLineOutput(VSConfig finalConfig)
121 | {
122 | var output = new StringBuilder();
123 |
124 | if (finalConfig.Components is not null)
125 | {
126 | foreach (var component in finalConfig.Components)
127 | {
128 | if (!string.IsNullOrEmpty(component))
129 | {
130 | output.AppendFormat("{0} {1} ", Add, component);
131 | }
132 | }
133 | }
134 |
135 | return output.ToString().TrimEnd();
136 | }
137 | }
138 | }
--------------------------------------------------------------------------------
/VSConfigFinder/VSConfigFinder.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net7.0
6 | enable
7 | enable
8 | true
9 | true
10 |
11 |
12 |
13 |
14 |
15 | all
16 | runtime; build; native; contentfiles; analyzers; buildtransitive
17 |
18 |
19 |
20 |
21 |
22 | Microsoft400
23 |
24 |
25 | Microsoft400
26 |
27 |
28 | 3PartySHA2
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/build.yml:
--------------------------------------------------------------------------------
1 | # Copyright (C) Microsoft Corporation. All rights reserved.
2 | # Licensed under the MIT license. See LICENSE.txt in the project root for license information.
3 |
4 | parameters:
5 | BuildConfiguration: Release
6 |
7 | steps:
8 | - task: UseDotNet@2
9 | displayName: 'Install .NET Core SDK'
10 | inputs:
11 | useGlobalJson: true
12 |
13 | - task: DotNetCoreCLI@2
14 | displayName: Build
15 | inputs:
16 | command: 'build'
17 | projects: 'VSConfigFinder'
18 | arguments: '--configuration $(BuildConfiguration)'
19 |
20 | - task: DotNetCoreCLI@2
21 | displayName: Test
22 | inputs:
23 | command: 'test'
24 | projects: 'VSConfigFinder.Test'
25 | arguments: '--configuration $(BuildConfiguration)'
26 |
27 | - task: DotNetCoreCLI@2
28 | displayName: Publish
29 | inputs:
30 | command: 'publish'
31 | arguments: '--no-build --configuration $(BuildConfiguration)'
32 | publishWebProjects: false
33 | zipAfterPublish: false
34 |
35 | - script: |
36 | choco pack pkg\VSConfigFinder\VSConfigFinder.nuspec --out "VSConfigFinder\bin\${{ parameters.BuildConfiguration }}" --version "$(GitBuildVersion)" "Configuration=${{ parameters.BuildConfiguration }}" "CommitId=$(Build.SourceVersion)" "Tag=$(Build.BuildNumber)"
37 | displayName: 'Package Nupkg'
38 | workingDirectory: $(Build.SourcesDirectory)
39 |
40 | - task: CopyFiles@2
41 | displayName: 'Copy build artifacts'
42 | inputs:
43 | SourceFolder: $(Build.SourcesDirectory)\VSConfigFinder
44 | Contents: |
45 | bin\$(BuildConfiguration)\**
46 | TargetFolder: $(Build.ArtifactStagingDirectory)\out
47 |
48 | - task: 1ES.PublishPipelineArtifact@1
49 | displayName: 'Publish build artifacts'
50 | inputs:
51 | targetPath: $(Build.ArtifactStagingDirectory)\out
52 | artifactName: drop
53 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "7.0.200",
4 | "rollForward": "feature"
5 | }
6 | }
--------------------------------------------------------------------------------
/pkg/VSConfigFinder/VSConfigFinder.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | VSConfigFinder
5 | $Version$
6 | Visual Studio Configuration Finder
7 | Microsoft
8 | VisualStudioSetup
9 | false
10 | https://go.microsoft.com/fwlink/?linkid=839265
11 | https://github.com/Microsoft/VSConfigFinder/tree/$CommitId$/LICENSE.txt
12 | https://github.com/Microsoft/VSConfigFinder
13 | Locate Visual Studio installation configuration files (.vsconfigs) downstream recursively and merge them all together
14 | Locate Visual Studio installation configuration files (.vsconfigs) downstream recursively and merge them all together
15 | © Microsoft Corporation. All rights reserved.
16 | vs vs2022 visualstudio
17 | true
18 | https://github.com/Microsoft/VSConfigFinder/tree/$CommitId$
19 | https://github.com/Microsoft/VSConfigFinder/tree/$CommitId$/pkg/VSConfigFinder
20 | https://github.com/microsoft/VSConfigFinder/blob/main/README.md
21 | https://github.com/Microsoft/VSConfigFinder/issues
22 | https://github.com/Microsoft/VSConfigFinder/releases/tag/$Tag$
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/pkg/VSConfigFinder/tools/VERIFICATION.txt:
--------------------------------------------------------------------------------
1 | VERIFICATION
2 | Verification is intended to assist the Chocolatey moderators and community
3 | in verifying that this package's contents are trustworthy.
4 |
5 | tools\VSConfigFinder.exe is produced by us from the same repository as this package: https://github.com/Microsoft/VSConfigFinder
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3 | "version": "1.0-beta",
4 | "publicReleaseRefSpec": [
5 | "^refs/heads/main$"
6 | ],
7 | "cloudBuild": {
8 | "buildNumber": {
9 | "enabled": true
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/vsts-ci.yml:
--------------------------------------------------------------------------------
1 | # Copyright (C) Microsoft Corporation. All rights reserved.
2 | # Licensed under the MIT license. See LICENSE.txt in the project root for license information.
3 |
4 | variables:
5 | BuildConfiguration: Release
6 | SignType: real
7 | TeamName: vssetup
8 |
9 | trigger:
10 | batch: true
11 | branches:
12 | include:
13 | - main
14 | paths:
15 | exclude:
16 | - README.md
17 |
18 | pr: none
19 |
20 | resources:
21 | repositories:
22 | - repository: MicroBuildTemplate
23 | type: git
24 | name: 1ESPipelineTemplates/MicroBuildTemplate
25 | ref: refs/tags/release
26 |
27 | extends:
28 | template: azure-pipelines/MicroBuild.1ES.Official.yml@MicroBuildTemplate
29 | parameters:
30 | pool:
31 | name: VSEngSS-MicroBuild2022-1ES
32 | sdl:
33 | sourceAnalysisPool:
34 | name: AzurePipelines-EO
35 | image: 1ESPT-Windows2022
36 | policheck:
37 | enabled: true
38 | binskim:
39 | enabled: true
40 | scanOutputDirectoryOnly: true # BinSkim scans whole source tree but we only need to scan the output dir.
41 | tsa:
42 | enabled: true
43 | configFile: $(Build.SourcesDirectory)\.config\tsaoptions.json
44 | onboard: false # We already onboarded
45 |
46 | stages:
47 | - stage: Build
48 | jobs:
49 | - job: Build
50 | templateContext:
51 | mb:
52 | signing:
53 | enabled: true
54 | signType: $(SignType)
55 |
56 | steps:
57 | - checkout: self
58 | fetchDepth: 0 # avoid shallow clone so nbgv can do its work.
59 |
60 | - template: /build.yml@self
61 | parameters:
62 | BuildConfiguration: $(BuildConfiguration)
63 |
--------------------------------------------------------------------------------
/vsts-compliance.yml:
--------------------------------------------------------------------------------
1 | # Copyright (C) Microsoft Corporation. All rights reserved.
2 | # Licensed under the MIT license. See LICENSE.txt in the project root for license information.
3 |
4 | variables:
5 | - group: vssetup-apiscan
6 | - name: BuildConfiguration
7 | value: Release
8 | - name: TeamName
9 | value: vssetup
10 |
11 | trigger:
12 | batch: true
13 | branches:
14 | include:
15 | - main
16 | paths:
17 | exclude:
18 | - README.md
19 |
20 | pr: none
21 |
22 | schedules:
23 | - cron: "0 12 * * 1"
24 | displayName: 'Run every Monday at 12:00 p.m.'
25 | branches:
26 | include:
27 | - main
28 | always: true
29 |
30 | resources:
31 | repositories:
32 | - repository: MicroBuildTemplate
33 | type: git
34 | name: 1ESPipelineTemplates/MicroBuildTemplate
35 | ref: refs/tags/release
36 |
37 | extends:
38 | template: azure-pipelines/MicroBuild.1ES.Unofficial.yml@MicroBuildTemplate
39 | parameters:
40 | pool:
41 | name: VSEngSS-MicroBuild2022-1ES
42 | sdl:
43 | sourceAnalysisPool:
44 | name: AzurePipelines-EO
45 | image: 1ESPT-Windows2022
46 | antimalwareScan:
47 | enabled: true
48 | armory:
49 | enabled: true
50 | binskim:
51 | enabled: true
52 | scanOutputDirectoryOnly: true
53 | codeql:
54 | compiled:
55 | enabled: true
56 | credscan:
57 | enabled: true
58 | policheck:
59 | enabled: true
60 | psscriptanalyzer:
61 | enabled: true
62 | prefast:
63 | enabled: true
64 | tsa:
65 | enabled: true
66 | configFile: $(Build.SourcesDirectory)\.config\tsaoptions.json
67 | onboard: false # We already onboarded
68 |
69 | stages:
70 | - stage: Compliance
71 | jobs:
72 | - job: Compliance
73 | steps:
74 | - template: /build.yml@self
75 | parameters:
76 | BuildConfiguration: $(BuildConfiguration)
77 |
78 | - task: CopyFiles@2
79 | displayName: Copy files for API scan
80 | inputs:
81 | SourceFolder: $(Build.SourcesDirectory)\VSConfigFinder\bin\$(BuildConfiguration)
82 | Contents: |
83 | **\VSConfigFinder.?(pdb|dll|xml)
84 | **\CommandLine.?(pdb|dll|xml)
85 | !**\*.Test.*
86 | TargetFolder: $(Build.StagingDirectory)\apiscan-inputs
87 |
88 | - task: APIScan@2
89 | displayName: Run APIScan
90 | inputs:
91 | softwareFolder: $(Build.StagingDirectory)\apiscan-inputs
92 | softwareName: 'Microsoft.VSConfigFinder'
93 | softwareVersionNum: '1'
94 | toolVersion: Latest
95 | env:
96 | AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanClientId)
97 |
98 | - task: PublishSecurityAnalysisLogs@3
99 | displayName: Publish 'SDLAnalysis-APIScan' artifact
100 | condition: succeededOrFailed()
101 | inputs:
102 | ArtifactName: SDLAnalysis-APIScan
103 | AllTools: false
104 | APIScan: true
105 |
106 | - task: PostAnalysis@2
107 | displayName: Post Analysis
108 | inputs:
109 | GdnBreakAllTools: false
110 | GdnBreakGdnToolApiScan: true
111 |
112 | - task: TSAUpload@2
113 | displayName: Upload APIScan results to TSA
114 | inputs:
115 | GdnPublishTsaOnboard: false
116 | GdnPublishTsaConfigFile: '$(Build.SourcesDirectory)\.config\tsaoptions.json'
117 | GdnPublishTsaExportedResultsPublishable: true
118 | continueOnError: true
119 | condition: succeededOrFailed()
120 | enabled: true
121 |
--------------------------------------------------------------------------------