Skip to content

Commit 073ff45

Browse files
authored
Merge f920f7d into ca2d168
2 parents ca2d168 + f920f7d commit 073ff45

File tree

308 files changed

+6630
-7148
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

308 files changed

+6630
-7148
lines changed

.github/workflows/main.yml

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ env:
66
SkipReleaseNotes: ${{ true }}
77

88
on:
9-
push:
10-
branches: [ main ]
119
pull_request:
1210
branches: [ main ]
13-
workflow_dispatch:
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
1415

1516
jobs:
1617

@@ -90,10 +91,12 @@ jobs:
9091
shell: pwsh
9192
run: |
9293
$fileName = (Get-ChildItem [0-9]*.md -Recurse | Sort-Object Name | Select -ExpandProperty FullName -Last 1)
93-
echo $fileName
94-
$releaseNotes = (Get-Content $fileName -Encoding UTF8 | Select-Object -Skip 4) -join '%0A'
95-
echo $releaseNotes
96-
Write-Output "::set-output name=RELEASE_NOTES::$releaseNotes"
94+
Write-Output $fileName
95+
$releaseNotes = (Get-Content $fileName -Encoding UTF8 | Select-Object -Skip 4)
96+
Write-Output $releaseNotes
97+
Write-Output 'RELEASE_NOTES<<EOF' >> $env:GITHUB_OUTPUT
98+
Write-Output $releaseNotes >> $env:GITHUB_OUTPUT
99+
Write-Output 'EOF' >> $env:GITHUB_OUTPUT
97100
- name: Create Draft Release
98101
id: create_release
99102
shell: pwsh
@@ -132,15 +135,10 @@ jobs:
132135
runs-on: ubuntu-latest
133136
environment: production
134137
needs: [ Staging ]
135-
if: ${{ github.event_name != 'pull_request' }}
136138
env:
137139
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
138140
BUILD_NAME: ${{ needs.Staging.outputs.BUILD_NAME }}
139141
steps:
140-
- name: Cancel Previous Runs
141-
uses: styfle/[email protected]
142-
with:
143-
access_token: ${{ github.token }}
144142
- name: Promote release
145143
id: promote_release
146144
shell: pwsh
@@ -155,8 +153,8 @@ jobs:
155153
$rel = Get-GitHubRelease `
156154
| Where-Object { ($_.Draft -eq $true) -and ($_.Name -eq "Release $($env:BUILD_NAME)") }
157155
Set-GitHubRelease -Release $rel.id -Draft:$false
158-
Write-Output "::set-output name=RELEASE_URL::$($rel.html_url)"
159-
Write-Output "::set-output name=RELEASE_TAG::$($env:BUILD_NAME.Replace('+', '%2B'))"
156+
Write-Output "RELEASE_URL=$($rel.html_url)" >> $env:GITHUB_OUTPUT
157+
Write-Output "RELEASE_TAG=$($env:BUILD_NAME.Replace('+', '%2B'))" >> $env:GITHUB_OUTPUT
160158
outputs:
161159
BUILD_NAME: ${{ needs.Staging.outputs.BUILD_NAME }}
162160
RELEASE_NOTES: ${{ needs.Staging.outputs.RELEASE_NOTES }}
@@ -167,7 +165,6 @@ jobs:
167165

168166
runs-on: ubuntu-latest
169167
needs: [ Release ]
170-
if: ${{ github.event_name != 'pull_request' }}
171168
env:
172169
BUILD_NAME: ${{ needs.Release.outputs.BUILD_NAME }}
173170
RELEASE_NOTES: ${{ needs.Release.outputs.RELEASE_NOTES }}
@@ -187,8 +184,8 @@ jobs:
187184
git checkout --track origin/gh-pages
188185
unzip -o ../../TfsCmdlets-Docs-*.zip
189186
popd
190-
echo build_info: TfsCmdlets v${BUILD_NAME}, released $(date +%F) >> _config.yml
191-
echo >> _config.yml
187+
Write-Output build_info: TfsCmdlets v${BUILD_NAME}, released $(date +%F) >> _config.yml
188+
Write-Output >> _config.yml
192189
git config --local user.name "Igor Abade"
193190
git config --local user.email [email protected]
194191
git add *
@@ -200,7 +197,6 @@ jobs:
200197
runs-on: ubuntu-latest
201198
needs: [ Release ]
202199
environment: psgallery
203-
if: ${{ github.event_name != 'pull_request' }}
204200
env:
205201
RELEASE_NOTES: ${{ needs.Release.outputs.RELEASE_NOTES }}
206202
PSGALLERY_KEY: ${{ secrets.API_KEY }}
@@ -223,7 +219,6 @@ jobs:
223219
runs-on: ubuntu-latest
224220
needs: [ Release ]
225221
environment: nuget
226-
if: ${{ github.event_name != 'pull_request' }}
227222
steps:
228223
- name: Download artifact
229224
uses: actions/download-artifact@v4
@@ -243,7 +238,6 @@ jobs:
243238
runs-on: windows-latest
244239
needs: [ Release ]
245240
environment: chocolatey
246-
if: ${{ github.event_name != 'pull_request' }}
247241
env:
248242
CHOCO_KEY: ${{ secrets.API_KEY }}
249243
steps:
@@ -266,7 +260,6 @@ jobs:
266260
runs-on: ubuntu-latest
267261
needs: [ Release ]
268262
environment: winget
269-
if: ${{ github.event_name != 'pull_request' }}
270263
env:
271264
GITHUB_TOKEN: ${{ secrets.API_GITHUB_TOKEN }}
272265
BUILD_NAME: ${{ needs.Release.outputs.BUILD_NAME }}
@@ -324,7 +317,7 @@ jobs:
324317
steps:
325318
- name: No-op
326319
shell: bash
327-
run: echo "no-op"
320+
run: Write-Output "no-op"
328321
# - name: Tweet
329322
# id: tweet
330323
# uses: snow-actions/[email protected]

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,4 @@ CSharp/.idea/**
218218
# Miscellaneous files
219219

220220
CSharp/*/Generated/**
221+
Docs/AzDO-Security-Actions.csv

Build.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ try {
132132
$isCI = $true
133133
}
134134
elseif ($env:GITHUB_ACTIONS) {
135-
Write-Output "::set-output name=BUILD_NAME::$BuildName"
135+
Write-Output "BUILD_NAME=$BuildName" >> $env:GITHUB_OUTPUT
136136
$isCI = $true
137137
}
138138

CSharp/TfsCmdlets.Common/Cmdlets/TfsCmdletAttribute.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public sealed class TfsCmdletAttribute : Attribute
3131

3232
public bool ReturnsValue { get; set; }
3333

34+
public string AdditionalCredentialParameterSets { get; set; }
35+
3436
public TfsCmdletAttribute(CmdletScope scope = CmdletScope.None)
3537
{
3638
Scope = scope;

CSharp/TfsCmdlets.Common/Extensions/ObjectExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ public static object CallHiddenMethod(this object self, string methodName, param
4040
return method.Invoke(self, parameters);
4141
}
4242

43-
public static string ToJsonString(this object self)
43+
public static string ToJsonString(this object self, bool compress = true)
4444
{
45-
return Newtonsoft.Json.JsonConvert.SerializeObject(self, Newtonsoft.Json.Formatting.None);
45+
return Newtonsoft.Json.JsonConvert.SerializeObject(self, compress? Newtonsoft.Json.Formatting.None: Newtonsoft.Json.Formatting.Indented);
4646
}
4747

4848
private static T FindMember<T>(object self, string memberName)

CSharp/TfsCmdlets.Common/Services/Impl/LoggerImpl.cs

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ public void LogError(Exception ex, string errorId = null, ErrorCategory category
2424
var innerException = ex.InnerException ?? ex;
2525
var id = errorId ?? innerException.GetType().Name;
2626

27-
PowerShell.WriteError(new ErrorRecord(ex, id, category, targetObject));
27+
try
28+
{
29+
Log($"Detailed Error:\n{ex.ToJsonString(false)})");
30+
}
31+
finally
32+
{
33+
PowerShell.WriteError(new ErrorRecord(ex, id, category, targetObject));
34+
}
2835
}
2936

3037
public void LogWarn(string message)
@@ -38,7 +45,7 @@ public void LogParameters(string commandName, IParameterManager parameters)
3845
if (!PowerShell.IsVerbose) return;
3946

4047
var parms = new Dictionary<string, object>();
41-
var parameterSetName = parameters["ParameterSetName"]?? "__AllParameterSets";
48+
var parameterSetName = parameters["ParameterSetName"] ?? "__AllParameterSets";
4249
var hasParameterSetName = !parameterSetName.Equals("__AllParameterSets");
4350

4451
foreach (var key in parameters.Keys.Where(key => !key.Equals("ParameterSetName")))
@@ -57,30 +64,33 @@ public void LogParameters(string commandName, IParameterManager parameters)
5764
value = switchParameter.IsPresent;
5865
break;
5966
}
60-
case Models.Connection conn: {
61-
value = $"{{Connection Url={conn.Uri}}}";
62-
break;
63-
}
64-
case WebApiTeamProject tp: {
65-
value = $"{{Project Name='{tp.Name}' Id={tp.Id}}}";
66-
break;
67-
}
68-
case WebApiTeam t: {
69-
value = $"{{Team Name='{t.Name}' Id={t.Id}}}";
70-
break;
71-
}
67+
case Models.Connection conn:
68+
{
69+
value = $"{{Connection Url={conn.Uri}}}";
70+
break;
71+
}
72+
case WebApiTeamProject tp:
73+
{
74+
value = $"{{Project Name='{tp.Name}' Id={tp.Id}}}";
75+
break;
76+
}
77+
case WebApiTeam t:
78+
{
79+
value = $"{{Team Name='{t.Name}' Id={t.Id}}}";
80+
break;
81+
}
7282
}
7383
parms[key] = value;
7484
}
7585

76-
var args = Newtonsoft.Json.Linq.JObject.FromObject(parms)
77-
.ToString(Newtonsoft.Json.Formatting.None)
78-
.Replace("\":", "\" = ")
79-
.Replace(",\"", "; \"");
80-
81-
Log($"Running [{commandName}] with {(hasParameterSetName ? $"parameter set '{parameterSetName}' and " : "")}the following implicit and explicit arguments:");
82-
Log(args);
86+
var args = parms.ToJsonString(compress: false)
87+
.Replace("\":", "\" =")
88+
.Replace(",\"", "; \"")
89+
.Trim('{', '}')
90+
.Split(';');
8391

92+
Log($"Running [{commandName}] with {(hasParameterSetName ? $"parameter set '{parameterSetName}' and " : "")}" +
93+
$"the following implicit and explicit arguments:\n{string.Join("\n", args)}");
8494
}
8595

8696
[ImportingConstructor]

CSharp/TfsCmdlets.SourceGenerators/Generators/Cmdlets/CmdletInfo.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public class CmdletInfo : GeneratorState
2525
public string CmdletAttribute { get; private set; }
2626
public string OutputTypeAttribute { get; private set; }
2727

28+
public string AdditionalCredentialParameterSets { get; private set; }
29+
2830
public CmdletInfo(INamedTypeSymbol cmdlet, Logger logger)
2931
: base(cmdlet, logger)
3032
{
@@ -46,6 +48,7 @@ public CmdletInfo(INamedTypeSymbol cmdlet, Logger logger)
4648
CustomControllerName = cmdlet.GetAttributeNamedValue<string>("TfsCmdletAttribute", "CustomControllerName");
4749
ReturnsValue = cmdlet.GetAttributeNamedValue<bool>("TfsCmdletAttribute", "ReturnsValue");
4850
SkipGetProperty = cmdlet.GetAttributeNamedValue<bool>("TfsCmdletAttribute", "SkipGetProperty");
51+
AdditionalCredentialParameterSets = cmdlet.GetAttributeNamedValue<string>("TfsCmdletAttribute", "AdditionalCredentialParameterSets");
4952
CmdletAttribute = GenerateCmdletAttribute(this);
5053
OutputTypeAttribute = GenerateOutputTypeAttribute(this);
5154

@@ -95,7 +98,8 @@ private static IEnumerable<GeneratedProperty> GenerateScopeProperty(CmdletScope
9598
var isGetScopedCmdlet = IsGetScopeCmdlet(settings);
9699
var isPipeline = IsPipelineProperty(currentScope, settings);
97100
var valueFromPipeline = isPipeline ? "ValueFromPipeline=true" : string.Empty;
98-
var parameterSetNames = isGetScopedCmdlet ? _credentialParameterSetNames.Select(s => $"ParameterSetName=\"{s}\"") : new[] { string.Empty };
101+
var additionalParameterSets = settings.AdditionalCredentialParameterSets?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) ?? new string[0];
102+
var parameterSetNames = isGetScopedCmdlet ? _credentialParameterSetNames.Union(additionalParameterSets).Select(s => $"ParameterSetName=\"{s}\"") : new[] { string.Empty };
99103
var attributes = new List<(string, string)>();
100104

101105
if (scopeName.Equals("Collection"))

CSharp/TfsCmdlets.Tests.UnitTests/TfsCmdlets.Tests.UnitTests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
8+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.2.0" PrivateAssets="all" />
99
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
1010
<PackageReference Include="NSubstitute" Version="4.2.2" />
1111
<PackageReference Include="NSubstitute.Analyzers.CSharp" Version="1.0.14" />

CSharp/TfsCmdlets/Cmdlets/Admin/GetConfigurationServerConnectionString.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System.Management.Automation;
22
using System.Management.Automation.Runspaces;
3+
using System.Xml.Linq;
4+
using TfsCmdlets.Models;
35

46
namespace TfsCmdlets.Cmdlets.Admin
57
{
@@ -45,4 +47,38 @@ partial class GetConfigurationConnectionString
4547
[Credential]
4648
public PSCredential Credential { get; set; } = PSCredential.Empty;
4749
}
50+
51+
[CmdletController]
52+
partial class GetConfigurationConnectionStringController
53+
{
54+
protected override IEnumerable Run()
55+
{
56+
if (Has_Session)
57+
{
58+
throw new NotImplementedException("Remote sessions are currently not supported");
59+
}
60+
61+
if (!Parameters.Get<string>("ComputerName").Equals("localhost", StringComparison.OrdinalIgnoreCase))
62+
{
63+
throw new NotImplementedException("Remote computers are currently not supported");
64+
}
65+
66+
var installationPath = Data.GetItem<TfsInstallationPath>(new {
67+
Component = TfsComponent.ApplicationTier
68+
});
69+
70+
var webConfigPath = Path.Combine(installationPath.InnerObject, "Web Services/Web.config");
71+
var webConfig = XDocument.Load(webConfigPath);
72+
73+
var connString = webConfig
74+
.Element("configuration")
75+
.Element("appSettings")
76+
.Descendants("add")
77+
.Where(el => el.Attribute("key").Value == "applicationDatabase")
78+
.Select(el => el.Attribute("value").Value)
79+
.FirstOrDefault();
80+
81+
return connString;
82+
}
83+
}
4884
}

0 commit comments

Comments
 (0)