Skip to content

Commit 3f685ef

Browse files
committed
Fixed merge conflict
2 parents 92d5c3d + cc0357a commit 3f685ef

File tree

9 files changed

+284
-27
lines changed

9 files changed

+284
-27
lines changed

.github/workflows/ci-cd.yml

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
name: CI/CD Pipeline
2+
3+
on: [push, pull_request, workflow_dispatch]
4+
5+
jobs:
6+
ci:
7+
name: Continuous Integration
8+
runs-on: ubuntu-latest
9+
outputs:
10+
latest_version: ${{ steps.tag_generator.outputs.new_version }}
11+
is_default_branch: ${{ steps.conditionals_handler.outputs.is_default_branch }}
12+
env:
13+
ARTIFACTS_FOLDER: ${{ github.workspace }}/Artifacts
14+
GITHUB_RUN_NUMBER: ${{ github.run_number }}
15+
steps:
16+
- name: Setup .NET
17+
uses: actions/setup-dotnet@v1
18+
with:
19+
dotnet-version: 5.0.x
20+
21+
- name: Data gatherer
22+
id: data_gatherer
23+
shell: pwsh
24+
run: |
25+
# Get default branch
26+
$repo = 'microsoft/OpenAPI.NET'
27+
$defaultBranch = Invoke-RestMethod -Method GET -Uri https://api.github.com/repos/$repo | Select-Object -ExpandProperty default_branch
28+
Write-Output "::set-output name=default_branch::$(echo $defaultBranch)"
29+
30+
- name: Conditionals handler
31+
id: conditionals_handler
32+
shell: pwsh
33+
run: |
34+
$defaultBranch = "${{ steps.data_gatherer.outputs.default_branch }}"
35+
$githubRef = "${{ github.ref }}"
36+
$isDefaultBranch = 'false'
37+
if ( $githubRef -like "*$defaultBranch*" ) {
38+
$isDefaultBranch = 'true'
39+
}
40+
Write-Output "::set-output name=is_default_branch::$(echo $isDefaultBranch)"
41+
42+
- name: Checkout repository
43+
id: checkout_repo
44+
uses: actions/checkout@v2
45+
with:
46+
token: ${{ secrets.GITHUB_TOKEN }}
47+
fetch-depth: 0
48+
49+
- if: steps.conditionals_handler.outputs.is_default_branch == 'true'
50+
name: Bump GH tag
51+
id: tag_generator
52+
uses: mathieudutour/[email protected]
53+
with:
54+
github_token: ${{ secrets.GITHUB_TOKEN }}
55+
default_bump: false
56+
release_branches: ${{ steps.data_gatherer.outputs.default_branch }}
57+
58+
- name: Build projects
59+
id: build_projects
60+
shell: pwsh
61+
run: |
62+
$projectsArray = @(
63+
'.\src\Microsoft.OpenApi\Microsoft.OpenApi.csproj',
64+
'.\src\Microsoft.OpenApi.Readers\Microsoft.OpenApi.Readers.csproj',
65+
'.\src\Microsoft.OpenApi.Tool\Microsoft.OpenApi.Tool.csproj'
66+
)
67+
$gitNewVersion = if ("${{ steps.tag_generator.outputs.new_version }}") {"${{ steps.tag_generator.outputs.new_version }}"} else {$null}
68+
$projectCurrentVersion = ([xml](Get-Content .\src\Microsoft.OpenApi\Microsoft.OpenApi.csproj)).Project.PropertyGroup.Version
69+
$projectNewVersion = $gitNewVersion ?? $projectCurrentVersion
70+
71+
$projectsArray | ForEach-Object {
72+
dotnet build $PSItem `
73+
-c Release # `
74+
# -o $env:ARTIFACTS_FOLDER `
75+
# /p:Version=$projectNewVersion
76+
}
77+
78+
# Move NuGet packages to separate folder for pipeline convenience
79+
# New-Item Artifacts/NuGet -ItemType Directory
80+
# Get-ChildItem Artifacts/*.nupkg | Move-Item -Destination "Artifacts/NuGet"
81+
82+
- name: Run unit tests
83+
id: run_unit_tests
84+
shell: pwsh
85+
run: |
86+
$testProjectsArray = @(
87+
'.\test\Microsoft.OpenApi.Tests\Microsoft.OpenApi.Tests.csproj',
88+
'.\test\Microsoft.OpenApi.Readers.Tests\Microsoft.OpenApi.Readers.Tests.csproj',
89+
'.\test\Microsoft.OpenApi.SmokeTests\Microsoft.OpenApi.SmokeTests.csproj'
90+
)
91+
92+
$testProjectsArray | ForEach-Object {
93+
dotnet test $PSItem `
94+
-c Release
95+
}
96+
97+
# - if: steps.tag_generator.outputs.new_version != ''
98+
# name: Upload NuGet packages as artifacts
99+
# id: ul_packages_artifact
100+
# uses: actions/upload-artifact@v1
101+
# with:
102+
# name: NuGet packages
103+
# path: Artifacts/NuGet/
104+
105+
cd:
106+
if: needs.ci.outputs.is_default_branch == 'true' && needs.ci.outputs.latest_version != ''
107+
name: Continuous Deployment
108+
needs: ci
109+
runs-on: ubuntu-latest
110+
steps:
111+
# - name: Download and extract NuGet packages
112+
# id: dl_packages_artifact
113+
# uses: actions/download-artifact@v2
114+
# with:
115+
# name: NuGet packages
116+
# path: NuGet/
117+
118+
# - name: Push NuGet packages to NuGet.org
119+
# id: push_nuget_packages
120+
# continue-on-error: true
121+
# shell: pwsh
122+
# run: |
123+
# Get-ChildItem NuGet/*.nupkg | ForEach-Object {
124+
# nuget push $PSItem `
125+
# -ApiKey $env:NUGET_API_KEY `
126+
# -Source https://api.nuget.org/v3/index.json
127+
# }
128+
# env:
129+
# NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
130+
131+
- name: Create and publish release
132+
id: create_release
133+
uses: softprops/action-gh-release@v1
134+
with:
135+
name: OpenApi v${{ needs.ci.outputs.latest_version }}
136+
tag_name: v${{ needs.ci.outputs.latest_version }}
137+
# files: |
138+
# NuGet/Microsoft.OpenApi.${{ needs.ci.outputs.latest_version }}.nupkg
139+
# NuGet/Microsoft.OpenApi.Readers.${{ needs.ci.outputs.latest_version }}.nupkg
140+
env:
141+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
142+
143+
# Built with ❤ by [Pipeline Foundation](https://pipeline.foundation)

docs/CI-CD_DOCUMENTATION.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# CI/CD documentation
2+
3+
## 1. Run workflow manually
4+
5+
1. Go to the project's GitHub repository and click on the **Actions** tab
6+
7+
2. From the "Workflows" list on the left, click on "CI/CD Pipeline"
8+
9+
3. On the right, next to the "This workflow has a workflow_dispatch event trigger" label, click on the "Run workflow" dropdown, make sure the default branch is selected (if not manually changed, should be main or master) in the "Use workflow from" dropdown and click the "Run workflow" button
10+
11+
![Actions_workflow_dispatch](images/Actions_workflow_dispatch.png)
12+
13+
NOTE: **screenshots are only exemplary**
14+
15+
<br>
16+
17+
## 2. Automated NuGet publishing
18+
19+
To setup the automated publishing to NuGet:
20+
21+
1. Go to the repo **Settings** tab -> **Secrets**
22+
23+
2. Add a secret with the name `NUGET_API_KEY` and as value use an API key from NuGet.org that is assigned to the packages for this project
24+
25+
NOTE: the automated NuGet publishing is execute **only** when a release is triggered by the ["Automated versioning" feature](#3-automated-versioning)
26+
27+
<br>
28+
29+
## 3. Automated versioning
30+
31+
Automatically bumps up the GitHub tag in the repo and executes the CD job
32+
33+
Note: **not every commit to your default branch creates a release**
34+
35+
Follow these instructions for any commit (push or PR merge) to your default branch, you would like to execute the automated versioning.
36+
37+
You would need one of three keywords at the start of your commit title. Each of the three keywords corresponds to a number in your release version i.e. v1.2.3. The release versioning uses the ["Conventional Commits" specification](https://www.conventionalcommits.org/en/v1.0.0/):
38+
39+
- "fix: ..." - this keyword corresponds to the last number v1.2.**3**, also known as PATCH;
40+
- "feat: ..." - this keyword corresponds to the middle number v1.**2**.3, also known as MINOR;
41+
- "perf: ..." - this keyword corresponds to the first number v**1**.2.3, also known as MAJOR. In addition, to trigger a MAJOR release, you would need to write "BREAKING CHANGE: ..." in the description of the commit, with an empty line above it to indicate it is in the <footer> portion of the description;
42+
43+
Note: when making a MAJOR release by committing through a terminal, use the multiple line syntax to add the commit title on one line and then adding an empty line, and then adding the "BREAKING CHANGE: " label
44+
<br><br>
45+
46+
#### Examples
47+
48+
Example(fix/PATCH): <br>
49+
`git commit -a -m "fix: this is a PATCH release triggering commit"`
50+
<br>
51+
`git push origin vnext`
52+
<br>
53+
Result: v1.2.3 -> **v1.2.4**
54+
<br>
55+
<br>
56+
<br>
57+
Example(feat/MINOR): <br>
58+
`git commit -a -m "feat: this is a MINOR release triggering commit"`
59+
<br>
60+
`git push origin vnext`
61+
<br>
62+
Result: v1.2.3 -> **v1.3.0**
63+
<br>
64+
<br>
65+
<br>
66+
Example(perf/MAJOR): <br>
67+
`` git commit -a -m "perf: this is a MAJOR release triggering commit ` ``
68+
<br>
69+
&gt;&gt; <br>
70+
&gt;&gt; `BREAKING CHANGE: this is the breaking change"`
71+
<br>
72+
`git push origin vnext`
73+
<br>
74+
Result: v1.2.3 -> **v2.0.0**
75+
<br>
76+
<br>
77+
Note: in the MAJOR release example, the PowerShell multiline syntax ` (backtick) is used. After writing a backtick, a press of the Enter key should open a new line.
78+
79+
#
80+
81+
Built with ❤ by [Pipeline Foundation](https://pipeline.foundation)
38.8 KB
Loading

src/Microsoft.OpenApi.Readers/ParseNodes/MapNode.cs

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public override Dictionary<string, T> CreateMap<T>(Func<MapNode, T> map)
9393

9494
public override Dictionary<string, T> CreateMapWithReference<T>(
9595
ReferenceType referenceType,
96-
Func<MapNode, T> map)
96+
Func<MapNode, T> map)
9797
{
9898
var yamlMap = _node;
9999
if (yamlMap == null)
@@ -104,28 +104,37 @@ public override Dictionary<string, T> CreateMapWithReference<T>(
104104
var nodes = yamlMap.Select(
105105
n =>
106106
{
107-
var entry = new
108-
{
109-
key = n.Key.GetScalarValue(),
110-
value = map(new MapNode(Context, (YamlMappingNode)n.Value))
111-
};
112-
if (entry.value == null)
113-
{
114-
return null; // Body Parameters shouldn't be converted to Parameters
115-
}
116-
// If the component isn't a reference to another component, then point it to itself.
117-
if (entry.value.Reference == null)
107+
var key = n.Key.GetScalarValue();
108+
(string key, T value) entry;
109+
try
118110
{
119-
entry.value.Reference = new OpenApiReference()
111+
Context.StartObject(key);
112+
entry = (
113+
key: key,
114+
value: map(new MapNode(Context, (YamlMappingNode)n.Value))
115+
);
116+
if (entry.value == null)
117+
{
118+
return default; // Body Parameters shouldn't be converted to Parameters
119+
}
120+
// If the component isn't a reference to another component, then point it to itself.
121+
if (entry.value.Reference == null)
120122
{
121-
Type = referenceType,
122-
Id = entry.key
123-
};
123+
entry.value.Reference = new OpenApiReference()
124+
{
125+
Type = referenceType,
126+
Id = entry.key
127+
};
128+
}
129+
}
130+
finally
131+
{
132+
Context.EndObject();
124133
}
125134
return entry;
126135
}
127136
);
128-
return nodes.Where(n => n != null).ToDictionary(k => k.key, v => v.value);
137+
return nodes.Where(n => n != default).ToDictionary(k => k.key, v => v.value);
129138
}
130139

131140
public override Dictionary<string, T> CreateSimpleMap<T>(Func<ValueNode, T> map)
@@ -137,10 +146,21 @@ public override Dictionary<string, T> CreateSimpleMap<T>(Func<ValueNode, T> map)
137146
}
138147

139148
var nodes = yamlMap.Select(
140-
n => new
149+
n =>
141150
{
142-
key = n.Key.GetScalarValue(),
143-
value = map(new ValueNode(Context, (YamlScalarNode)n.Value))
151+
var key = n.Key.GetScalarValue();
152+
try
153+
{
154+
Context.StartObject(key);
155+
YamlScalarNode scalarNode = n.Value as YamlScalarNode;
156+
if (scalarNode == null)
157+
{
158+
throw new OpenApiReaderException($"Expected scalar while parsing {typeof(T).Name}", Context);
159+
}
160+
return (key, value: map(new ValueNode(Context, (YamlScalarNode)n.Value)));
161+
} finally {
162+
Context.EndObject();
163+
}
144164
});
145165
return nodes.ToDictionary(k => k.key, v => v.value);
146166
}

src/Microsoft.OpenApi/Validations/Rules/OpenApiMediaTypeRules.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,16 @@ namespace Microsoft.OpenApi.Validations.Rules
88
/// <summary>
99
/// The validation rules for <see cref="OpenApiMediaType"/>.
1010
/// </summary>
11-
[OpenApiRule]
11+
/// <remarks>
12+
/// Removed this in v1.3 as a default rule as the OpenAPI specification does not require that example
13+
/// values validate against the schema. Validating examples against the schema is particularly difficult
14+
/// as it requires parsing of the example using the schema as a guide. This is not possible when the schema
15+
/// is ref'd. Even if we fix this issue, this rule should be treated as a warning, not an error
16+
/// Future versions of the validator should make that distinction.
17+
/// Future versions of the example parsers should not try an infer types.
18+
/// Example validation should be done as a separate post reading step so all schemas can be fully available.
19+
/// </remarks>
20+
//[OpenApiRule]
1221
public static class OpenApiMediaTypeRules
1322
{
1423
/// <summary>

test/Microsoft.OpenApi.SmokeTests/ApiGurus.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ JToken GetProp(JToken obj, string prop)
7070
}
7171
}
7272

73-
// Disable as some APIs are currently invalid [Theory(DisplayName = "APIs.guru")]
74-
// [MemberData(nameof(GetSchemas))]
73+
// Disable as some APIs are currently invalid
74+
//[Theory(DisplayName = "APIs.guru")]
75+
//[MemberData(nameof(GetSchemas))]
7576
public async Task EnsureThatICouldParse(string url)
7677
{
7778
var response = await _httpClient.GetAsync(url);

test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,6 @@ namespace Microsoft.OpenApi.Validations.Rules
11541154
{
11551155
public static Microsoft.OpenApi.Validations.ValidationRule<Microsoft.OpenApi.Models.OpenApiLicense> LicenseRequiredFields { get; }
11561156
}
1157-
[Microsoft.OpenApi.Validations.Rules.OpenApiRule]
11581157
public static class OpenApiMediaTypeRules
11591158
{
11601159
public static Microsoft.OpenApi.Validations.ValidationRule<Microsoft.OpenApi.Models.OpenApiMediaType> MediaTypeMismatchedDataType { get; }

test/Microsoft.OpenApi.Tests/Validations/OpenApiMediaTypeValidationTests.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema()
3232
};
3333

3434
// Act
35-
var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet());
35+
var ruleset = ValidationRuleSet.GetDefaultRuleSet();
36+
ruleset.Add(OpenApiMediaTypeRules.MediaTypeMismatchedDataType);
37+
var validator = new OpenApiValidator(ruleset);
3638
var walker = new OpenApiWalker(validator);
3739
walker.Walk(mediaType);
3840

@@ -102,7 +104,9 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema()
102104
};
103105

104106
// Act
105-
var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet());
107+
var ruleset = ValidationRuleSet.GetDefaultRuleSet();
108+
ruleset.Add(OpenApiMediaTypeRules.MediaTypeMismatchedDataType);
109+
var validator = new OpenApiValidator(ruleset);
106110
var walker = new OpenApiWalker(validator);
107111
walker.Walk(mediaType);
108112

test/Microsoft.OpenApi.Tests/Validations/ValidationRuleSetTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public void DefaultRuleSetPropertyReturnsTheCorrectRules()
4343
Assert.NotEmpty(rules);
4444

4545
// Update the number if you add new default rule(s).
46-
Assert.Equal(22, rules.Count);
46+
Assert.Equal(21, rules.Count);
4747
}
4848
}
4949
}

0 commit comments

Comments
 (0)