Skip to content

Commit 20e2099

Browse files
committed
Set up NuGet packages and related CI infrastructure.
Related changes: * Updated to ClangSharp.Pathogen 0.0.0 (which is published on NuGet.org.) * Biohazrd is no longer marked as x64-only. * This restriction was in place primarily because ClangSharp.Pathogen only provides x64 matrix runtimes. While this is still true, nothing about Biohazrd its self is x64-only, and advanced users can manually provide their own libclang-pathogen for their platform as necessary. Closes #214
1 parent ad822e7 commit 20e2099

File tree

15 files changed

+390
-14
lines changed

15 files changed

+390
-14
lines changed

Diff for: .github/workflows/Biohazrd.yml

+155-4
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,200 @@
11
name: Biohazrd
22
on:
33
push:
4+
# This prevents tag pushes from triggering this workflow
5+
branches: ['*']
46
pull_request:
7+
release:
8+
types: [published]
59
workflow_dispatch:
10+
inputs:
11+
version:
12+
description: "Version"
13+
default: ""
14+
will_publish_packages:
15+
description: "Publish packages?"
16+
default: "false"
617
env:
718
DOTNET_NOLOGO: true
819
DOTNET_CLI_TELEMETRY_OPTOUT: true
920
DOTNET_GENERATE_ASPNET_CERTIFICATE: false
1021
ContinuousIntegrationBuild: true
22+
# This URL will be added to the restore sources if it isn't the official NuGet.org
23+
# (This is mainly intended to allow using the NuGet.org test servers to test CI in forks.)
24+
CiNuGetApiUrl: ${{secrets.NUGET_API_URL}}
1125
jobs:
1226
build-and-test:
1327
strategy:
1428
fail-fast: false
1529
matrix:
16-
os: ['windows-latest', 'ubuntu-latest']
30+
platform:
31+
- name: Windows
32+
architecture: x64
33+
runs-on: windows-latest
34+
- name: Linux
35+
architecture: x64
36+
runs-on: ubuntu-latest
1737
configuration: ['Debug', 'Release']
18-
name: Build and Test ${{matrix.configuration}} ${{matrix.os}}
19-
runs-on: ${{matrix.os}}
38+
include:
39+
# Linux Release x64 builds create packages (if applicable)
40+
- platform:
41+
runs-on: ubuntu-latest
42+
configuration: Release
43+
create-packages: true
44+
name: Build and Test ${{matrix.platform.name}} ${{matrix.platform.architecture}} ${{matrix.configuration}}
45+
runs-on: ${{matrix.platform.runs-on}}
2046
steps:
2147
# ----------------------------------------------------------------------- Checkout
2248
- name: Checkout
2349
uses: actions/checkout@v2
2450
with:
2551
submodules: recursive
2652

53+
# ----------------------------------------------------------------------- Setup Python
54+
- name: Setup Python 3.8
55+
uses: actions/setup-python@v2
56+
with:
57+
python-version: '3.8'
58+
2759
# ----------------------------------------------------------------------- Setup .NET
2860
- name: Setup .NET
2961
uses: actions/setup-dotnet@v1
3062
with:
3163
dotnet-version: 5.0.x
3264

65+
# ----------------------------------------------------------------------- Configure versioning
66+
- name: Configure build
67+
id: configuration
68+
run: python .github/workflows/configure-build.py
69+
env:
70+
github_event_name: ${{github.event_name}}
71+
github_ref: ${{github.ref}}
72+
github_run_number: ${{github.run_number}}
73+
release_version: ${{github.event.release.tag_name}}
74+
workflow_dispatch_version: ${{github.event.inputs.version}}
75+
workflow_dispatch_will_publish_packages: ${{github.event.inputs.will_publish_packages}}
76+
3377
# ----------------------------------------------------------------------- Build
3478
- name: Restore
3579
run: dotnet restore
3680

3781
- name: Build
3882
run: dotnet build --no-restore --configuration ${{matrix.configuration}}
83+
84+
- name: Pack
85+
id: pack
86+
if: matrix.create-packages
87+
run: dotnet pack --no-build --configuration ${{matrix.configuration}}
3988

4089
# ----------------------------------------------------------------------- Test
4190
- name: Test
4291
run: dotnet test --no-restore --no-build --configuration ${{matrix.configuration}} --verbosity normal
92+
93+
# ----------------------------------------------------------------------- Collect Artifacts
94+
- name: Collect NuGet Packages
95+
uses: actions/upload-artifact@v2
96+
# We always want to collect packages when they were produced
97+
if: steps.pack.outcome == 'success' && always()
98+
with:
99+
name: Packages
100+
if-no-files-found: error
101+
path: packages/**
102+
103+
publish-packages-github:
104+
name: Publish to GitHub
105+
runs-on: ubuntu-latest
106+
needs: build-and-test
107+
# Pushes always publish CI packages (configure-build.py will add the branch name to the version string for branches besides main)
108+
# Published releases always publish packages
109+
# A manual workflow only publishes packages if explicitly enabled
110+
if: github.event_name == 'push' || github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.will_publish_packages == 'true')
111+
steps:
112+
# ----------------------------------------------------------------------- Setup .NET
113+
- name: Setup .NET
114+
uses: actions/setup-dotnet@v1
115+
with:
116+
dotnet-version: 5.0.x
117+
118+
# ----------------------------------------------------------------------- Download built packages
119+
- name: Download built packages
120+
uses: actions/download-artifact@v2
121+
with:
122+
name: Packages
123+
124+
# ----------------------------------------------------------------------- Upload release assets
125+
- name: Upload release assets
126+
if: github.event_name == 'release'
127+
uses: actions/github-script@v4
128+
with:
129+
user-agent: actions/github-script for ${{github.repository}}
130+
script: |
131+
const fs = require('fs').promises;
132+
const path = require('path');
133+
const upload_url = context.payload.release.upload_url;
134+
135+
if (!upload_url) {
136+
throw "Missing release asset upload URL!";
137+
}
138+
139+
for (let filePath of await fs.readdir('.')) {
140+
const fileExtension = path.extname(filePath);
141+
if (fileExtension != '.nupkg' && fileExtension != '.snupkg') {
142+
continue;
143+
}
144+
145+
console.log(`Uploading '${filePath}'`);
146+
const contentLength = (await fs.stat(filePath)).size;
147+
const fileContents = await fs.readFile(filePath);
148+
await github.repos.uploadReleaseAsset({
149+
url: upload_url,
150+
headers: {
151+
'content-type': 'application/octet-stream',
152+
'content-length': contentLength
153+
},
154+
name: path.basename(filePath),
155+
data: fileContents
156+
});
157+
}
158+
159+
# ----------------------------------------------------------------------- Push to GitHub Packages
160+
- name: Push to GitHub Packages
161+
run: dotnet nuget push "*.nupkg" --skip-duplicate --no-symbols true --api-key ${{secrets.GITHUB_TOKEN}} --source https://nuget.pkg.github.com/${{github.repository_owner}}
162+
env:
163+
# This is a workaround for https://github.com/NuGet/Home/issues/9775
164+
DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER: 0
165+
166+
publish-packages-nuget-org:
167+
name: Publish to NuGet.org
168+
runs-on: ubuntu-latest
169+
needs: build-and-test
170+
environment: NuGet.org
171+
# Release builds always publish packages to NuGet.org
172+
# Workflow dispatch builds will only publish packages if enabled and an explicit version number is given
173+
# Make sure this logic matches configure-build.py to ensure we don't accidentally depend on sibling CI pre-release packages
174+
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && github.event.inputs.will_publish_packages == 'true' && github.event.inputs.version != '')
175+
steps:
176+
# ----------------------------------------------------------------------- Setup .NET
177+
- name: Setup .NET
178+
uses: actions/setup-dotnet@v1
179+
with:
180+
dotnet-version: 5.0.x
181+
182+
# ----------------------------------------------------------------------- Download built packages
183+
- name: Download built packages
184+
uses: actions/download-artifact@v2
185+
with:
186+
name: Packages
187+
188+
# ----------------------------------------------------------------------- Push to NuGet.org
189+
- name: Push to NuGet.org
190+
run: dotnet nuget push "*.nupkg" --api-key ${{secrets.NUGET_API_KEY}} --source ${{secrets.NUGET_API_URL}}
191+
env:
192+
# This is a workaround for https://github.com/NuGet/Home/issues/9775
193+
DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER: 0
43194

44195
send-ci-failure-notification:
45196
name: Send CI Failure Notification
46-
needs: build-and-test
197+
needs: [build-and-test, publish-packages-github, publish-packages-nuget-org]
47198
if: failure() && github.event_name != 'pull_request'
48199
continue-on-error: true
49200
runs-on: ubuntu-latest

Diff for: .github/workflows/configure-build.py

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env python3
2+
import os
3+
import re
4+
5+
import gha
6+
7+
#==================================================================================================
8+
# Get inputs
9+
#==================================================================================================
10+
def get_environment_variable(name):
11+
ret = os.getenv(name)
12+
13+
if ret is None:
14+
gha.print_error(f"Missing required parameter '{name}'")
15+
16+
if (ret == ''):
17+
return None
18+
19+
return ret
20+
21+
github_event_name = get_environment_variable('github_event_name')
22+
github_run_number = get_environment_variable('github_run_number')
23+
github_ref = get_environment_variable('github_ref')
24+
25+
#==================================================================================================
26+
# Determine build settings
27+
#==================================================================================================
28+
29+
# For GitHub refs besides main, include the branch/tag name in the default version string
30+
ref_part = ''
31+
if github_ref != 'refs/heads/main':
32+
ref = github_ref
33+
34+
# Strip the ref prefix
35+
branch_prefix = 'refs/heads/'
36+
tag_prefix = 'refs/tags/'
37+
if ref.startswith(branch_prefix):
38+
ref = ref[len(branch_prefix):]
39+
elif ref.startswith(tag_prefix):
40+
ref = f'tag-{ref[len(tag_prefix):]}'
41+
42+
# Replace illegal characters with dashes
43+
ref = re.sub('[^0-9A-Za-z-]', '-', ref)
44+
45+
# Make the ref part
46+
ref_part = f'-{ref}'
47+
48+
# Build the default version string
49+
version = f'0.0.0{ref_part}-ci{github_run_number}'
50+
is_for_release = False
51+
52+
# Handle non-default version strings
53+
# Make sure logic relating to is_for_release matches the publish-packages-nuget-org in the workflow
54+
if github_event_name == 'release':
55+
version = get_environment_variable('release_version')
56+
is_for_release = True
57+
elif github_event_name == 'workflow_dispatch':
58+
workflow_dispatch_version = get_environment_variable('workflow_dispatch_version')
59+
workflow_dispatch_will_publish_packages = get_environment_variable('workflow_dispatch_will_publish_packages')
60+
61+
if workflow_dispatch_version is not None:
62+
version = workflow_dispatch_version
63+
64+
if workflow_dispatch_will_publish_packages.lower() == 'true':
65+
is_for_release = True
66+
67+
# Trim leading v off of version if present
68+
if version.startswith('v'):
69+
version = version[1:]
70+
71+
# Validate the version number
72+
if not re.match('^\d+\.\d+\.\d+(-[0-9a-zA-Z.-]+)?$', version):
73+
gha.print_error(f"'{version}' is not a valid semver version!")
74+
75+
# If there are any errors at this point, make sure we exit with an error code
76+
gha.fail_if_errors()
77+
78+
#==================================================================================================
79+
# Emit MSBuild properties
80+
#==================================================================================================
81+
print(f"Configuring build environment to build{' and release' if is_for_release else ''} version {version}")
82+
gha.set_environment_variable('CiBuildVersion', version)
83+
gha.set_environment_variable('CiIsForRelease', str(is_for_release).lower())
84+
85+
#==================================================================================================
86+
# Final check to exit with an error code if any errors were printed
87+
#==================================================================================================
88+
gha.fail_if_errors()

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.vs/
22
bin/
33
obj/
4+
/packages/

Diff for: Biohazrd.AllInOne/Biohazrd.AllInOne.csproj

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net5.0</TargetFramework>
5+
6+
<!--
7+
This package is just a convenience package which brings in all the other components of Biohazrd.
8+
It does not contain code.
9+
-->
10+
<PackageId>Biohazrd</PackageId>
11+
<IncludeBuildOutput>false</IncludeBuildOutput>
12+
<IncludeSymbols>false</IncludeSymbols>
13+
14+
<!--
15+
This warning basically happens because this package has no assemblies but does have dependencies
16+
https://github.com/NuGet/Home/issues/8583
17+
-->
18+
<NoWarn>$(NoWarn);NU5128</NoWarn>
19+
</PropertyGroup>
20+
21+
<ItemGroup>
22+
<ProjectReference Include="..\Biohazrd.CSharp\Biohazrd.CSharp.csproj" />
23+
<ProjectReference Include="..\Biohazrd.OutputGeneration\Biohazrd.OutputGeneration.csproj" />
24+
<ProjectReference Include="..\Biohazrd.Transformation\Biohazrd.Transformation.csproj" />
25+
<ProjectReference Include="..\Biohazrd.Utilities\Biohazrd.Utilities.csproj" />
26+
<ProjectReference Include="..\Biohazrd\Biohazrd.csproj" />
27+
</ItemGroup>
28+
29+
</Project>

Diff for: Biohazrd.CSharp/Biohazrd.CSharp.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net5.0</TargetFramework>
5+
<PackageDescription>This package provides transformations and binding generation for C#.</PackageDescription>
56
</PropertyGroup>
67

78
<ItemGroup>

Diff for: Biohazrd.OutputGeneration/Biohazrd.OutputGeneration.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net5.0</TargetFramework>
5+
<PackageDescription>This package provides language-agnostic functionality for writing out code and other files.</PackageDescription>
56
</PropertyGroup>
67

78
<ItemGroup>

Diff for: Biohazrd.Transformation/Biohazrd.Transformation.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net5.0</TargetFramework>
5+
<PackageDescription>This package provides language-agnostic functionality for manipulating declaration trees.</PackageDescription>
56
</PropertyGroup>
67

78
<ItemGroup>

Diff for: Biohazrd.Utilities/Biohazrd.Utilities.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net5.0</TargetFramework>
5+
<PackageDescription>This package provides various language-agnostic helpers for Biohazrd generators.</PackageDescription>
56
</PropertyGroup>
67

78
<ItemGroup>

Diff for: Biohazrd.sln

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio Version 16
4-
VisualStudioVersion = 16.0.30011.22
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31612.314
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A8649210-1355-403A-8B2D-45BD759B1B32}"
77
ProjectSection(SolutionItems) = preProject
@@ -21,6 +21,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tooling", "tooling", "{09A8
2121
ProjectSection(SolutionItems) = preProject
2222
tooling\Common.csproj.props = tooling\Common.csproj.props
2323
tooling\Common.csproj.targets = tooling\Common.csproj.targets
24+
tooling\Common.props = tooling\Common.props
25+
tooling\Common.targets = tooling\Common.targets
2426
EndProjectSection
2527
EndProject
2628
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Biohazrd.Utilities", "Biohazrd.Utilities\Biohazrd.Utilities.csproj", "{12BCC25F-9712-4223-8E34-50B7C060D8E2}"
@@ -41,6 +43,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Biohazrd.CSharp.Tests", "Te
4143
EndProject
4244
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Biohazrd.OutputGeneration.Tests", "Tests\Biohazrd.OutputGeneration.Tests\Biohazrd.OutputGeneration.Tests.csproj", "{00E42A88-A883-4C43-BE2E-8A241A32EDA9}"
4345
EndProject
46+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Biohazrd.AllInOne", "Biohazrd.AllInOne\Biohazrd.AllInOne.csproj", "{093ABF1F-E8E2-4E24-BCEA-845255E5BC5F}"
47+
EndProject
4448
Global
4549
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4650
Debug|Any CPU = Debug|Any CPU
@@ -87,6 +91,10 @@ Global
8791
{00E42A88-A883-4C43-BE2E-8A241A32EDA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
8892
{00E42A88-A883-4C43-BE2E-8A241A32EDA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
8993
{00E42A88-A883-4C43-BE2E-8A241A32EDA9}.Release|Any CPU.Build.0 = Release|Any CPU
94+
{093ABF1F-E8E2-4E24-BCEA-845255E5BC5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
95+
{093ABF1F-E8E2-4E24-BCEA-845255E5BC5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
96+
{093ABF1F-E8E2-4E24-BCEA-845255E5BC5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
97+
{093ABF1F-E8E2-4E24-BCEA-845255E5BC5F}.Release|Any CPU.Build.0 = Release|Any CPU
9098
EndGlobalSection
9199
GlobalSection(SolutionProperties) = preSolution
92100
HideSolutionNode = FALSE

0 commit comments

Comments
 (0)