Skip to content

Commit f44f47f

Browse files
Merge pull request #13 from perpetualintelligence/v7
V7
2 parents 21f53fc + 094eeaf commit f44f47f

15 files changed

Lines changed: 513 additions & 63 deletions

File tree

.github/actions/push-package/action.yml

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,22 @@ inputs:
99
default: 'false'
1010
required: false
1111
config:
12-
description: 'The build configuration (Build or Release)'
12+
description: 'The build configuration (Debug or Release)'
1313
default: Release
1414
required: true
1515
version:
1616
description: 'The package version'
1717
required: true
1818
ghapikey:
19-
description: 'The Git Hub Api Key for package feed'
19+
description: 'The GitHub API Key for package feed'
2020
required: true
2121
nugetapikey:
22-
description: 'The Nuget Api Key for package feed'
22+
description: 'The NuGet API Key for package feed'
2323
required: true
2424
registry:
25-
description: 'The package registry (github or nuget)'
25+
description: 'The package registry (GitHub or NuGet)'
2626
default: github
2727
required: true
28-
outputs:
29-
coverage-line:
30-
description: 'Line coverage percentage'
31-
value: ${{ steps.extract-coverage.outputs.line }}
32-
coverage-branch:
33-
description: 'Branch coverage percentage'
34-
value: ${{ steps.extract-coverage.outputs.branch }}
3528
runs:
3629
using: "composite"
3730
steps:
@@ -41,51 +34,34 @@ runs:
4134
run: dotnet build ./src/${{ inputs.project }}/${{ inputs.project }}.csproj -c ${{ inputs.config }} --verbosity minimal
4235
shell: bash
4336

44-
# Test
37+
# Test and collect coverage
4538
- name: Test
4639
if: ${{ inputs.skiptest == 'false' }}
4740
run: dotnet test ./test/${{ inputs.project }}.Tests/${{ inputs.project }}.Tests.csproj -c ${{ inputs.config }} --verbosity minimal --collect:"XPlat Code Coverage" --results-directory ./coverage
4841
shell: bash
4942

50-
# Generate coverage report
51-
- name: Coverage Report
52-
if: ${{ inputs.skiptest == 'false' }}
53-
run: reportgenerator -reports:./coverage/**/coverage.cobertura.xml -targetdir:./coverage/report -reporttypes:JsonSummary
54-
shell: bash
55-
56-
# Extract line and branch coverage percentages
57-
- name: Extract Coverage
58-
id: extract-coverage
59-
if: ${{ inputs.skiptest == 'false' }}
60-
run: |
61-
LINE=$(cat ./coverage/report/Summary.json | python3 -c "import sys,json; d=json.load(sys.stdin); print(round(d['summary']['linecoverage']))")
62-
BRANCH=$(cat ./coverage/report/Summary.json | python3 -c "import sys,json; d=json.load(sys.stdin); print(round(d['summary']['branchcoverage']))")
63-
echo "line=$LINE" >> $GITHUB_OUTPUT
64-
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
65-
shell: bash
66-
6743
# Pack
6844
- name: Pack
6945
run: |
7046
echo branch=${{ github.ref_name }} version=${{ inputs.version }}
7147
dotnet pack ./src/${{ inputs.project }}/${{ inputs.project }}.csproj -p:PackageVersion=${{ inputs.version }} --no-build -c ${{ inputs.config }} -o _packages -v minimal
7248
shell: bash
7349

74-
# GITHUB FEED
75-
- name: Github Push
50+
# GitHub Feed
51+
- name: GitHub Push
7652
if: ${{ inputs.registry == 'github' }}
7753
run: dotnet nuget push _packages/${{ inputs.project }}.${{ inputs.version }}.nupkg --skip-duplicate --no-symbols --api-key ${{ inputs.ghapikey }} --source github
7854
shell: bash
7955

80-
# NUGET FEED
81-
# First push to github (for package cadence, Nuget requires package verification)
82-
- name: Github Push
56+
# NuGet Feed
57+
# First push to GitHub (for package cadence, NuGet requires package verification)
58+
- name: GitHub Push
8359
if: ${{ inputs.registry == 'nuget' }}
8460
run: dotnet nuget push _packages/${{ inputs.project }}.${{ inputs.version }}.nupkg --skip-duplicate --no-symbols --api-key ${{ inputs.ghapikey }} --source github
8561
shell: bash
8662

87-
# Second push to Nuget (for package cadence, Github will be used and in production Nuget after package verification)
88-
- name: Nuget Push
63+
# Second push to NuGet (for package cadence, GitHub will be used and in production NuGet after package verification)
64+
- name: NuGet Push
8965
if: ${{ inputs.registry == 'nuget' }}
9066
run: dotnet nuget push _packages/${{ inputs.project }}.${{ inputs.version }}.nupkg --skip-duplicate --no-symbols --api-key ${{ inputs.nugetapikey }} --source nuget.org
9167
shell: bash

.github/copilot-instructions.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copilot Instructions
2+
3+
## Project Guidelines
4+
- Never add section separator comments (e.g., // ── SectionName ──────) in code.

.github/workflows/build-test-cross.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ jobs:
6666
- name: Checkout
6767
uses: actions/checkout@v6
6868

69+
# Read env
70+
- name: Read Env
71+
run: cat .github/package_version.env >> $GITHUB_ENV
72+
continue-on-error: false
73+
6974
# Setup .Net with global.json
7075
- name: Setup .NET
7176
uses: actions/setup-dotnet@v5
@@ -99,6 +104,11 @@ jobs:
99104
- name: Checkout
100105
uses: actions/checkout@v6
101106

107+
# Read env
108+
- name: Read Env
109+
run: cat .github/package_version.env >> $GITHUB_ENV
110+
continue-on-error: false
111+
102112
# Setup .Net with global.json
103113
- name: Setup .NET
104114
uses: actions/setup-dotnet@v5

.github/workflows/build-test-push.yml

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
name: build-test-push
77

88
# 1 release at a time
9-
concurrency: shared
9+
concurrency: ${{ github.event.repository.name }}
1010

1111
# CICD. The rc and release are a manual trigger
1212
on:
@@ -116,14 +116,13 @@ jobs:
116116
run: dotnet tool install --global dotnet-reportgenerator-globaltool
117117
continue-on-error: false
118118

119-
# Setup local
120-
# OneImlx.Shared is the first package so we use the local project reference to avoid cyclic Nuget dependency resolution.
119+
# OneImlx.Shared is the first package so we use the cross project reference to avoid cyclic Nuget dependency resolution.
121120
# See OneImlx.Shared.Test.csproj for more info.
122-
- name: Force local
121+
- name: Force cross
123122
run: echo "PI_CI_REFERENCE=cross" >> $GITHUB_ENV
124123
continue-on-error: false
125124

126-
# Publish OneImlx.Shared
125+
# Publish OneImlx.Shared (deposits coverage into ./coverage)
127126
- name: OneImlx.Shared
128127
id: oneimlx-shared
129128
uses: ./.github/actions/push-package
@@ -135,7 +134,7 @@ jobs:
135134
nugetapikey: ${{ env.PI_NUGET_PAT_ENV }}
136135
registry: ${{ env.PI_PUBLISH_REGISTRY }}
137136

138-
# Setup package
137+
# Switch to package references for downstream packages
139138
- name: Force package
140139
run: echo "PI_CI_REFERENCE=package" >> $GITHUB_ENV
141140
continue-on-error: false
@@ -146,13 +145,25 @@ jobs:
146145
uses: ./.github/actions/push-package
147146
with:
148147
project: OneImlx.Test
149-
skiptest: 'true'
150148
config: Release
151149
version: ${{ env.PI_CI_PACKAGE_VERSION }}
152150
ghapikey: ${{ env.PI_GITHUB_PAT_ENV }}
153151
nugetapikey: ${{ env.PI_NUGET_PAT_ENV }}
154152
registry: ${{ env.PI_PUBLISH_REGISTRY }}
155153

154+
# Aggregate coverage report across all packages deposited into ./coverage
155+
- name: Coverage Report
156+
run: reportgenerator -reports:./coverage/**/coverage.cobertura.xml -targetdir:./coverage/report -reporttypes:JsonSummary
157+
shell: bash
158+
159+
# Extract aggregate line and branch coverage
160+
- name: Extract Coverage
161+
id: coverage
162+
run: |
163+
echo "line=$(jq '.summary.linecoverage' ./coverage/report/Summary.json | xargs printf '%.0f')" >> $GITHUB_OUTPUT
164+
echo "branch=$(jq '.summary.branchcoverage' ./coverage/report/Summary.json | xargs printf '%.0f')" >> $GITHUB_OUTPUT
165+
shell: bash
166+
156167
# Update line coverage badge in Gist
157168
- name: Line Coverage Badge
158169
uses: Schneegans/dynamic-badges-action@v1.8.0
@@ -161,8 +172,8 @@ jobs:
161172
gistID: ${{ secrets.PI_GITHUB_GIST_ID }}
162173
filename: coverage_${{ github.event.repository.name }}_line.json
163174
label: coverage-line
164-
message: ${{ steps.oneimlx-shared.outputs.coverage-line }}%
165-
valColorRange: ${{ steps.oneimlx-shared.outputs.coverage-line }}
175+
message: ${{ steps.coverage.outputs.line }}%
176+
valColorRange: ${{ steps.coverage.outputs.line }}
166177
maxColorRange: 100
167178
minColorRange: 0
168179

@@ -174,7 +185,7 @@ jobs:
174185
gistID: ${{ secrets.PI_GITHUB_GIST_ID }}
175186
filename: coverage_${{ github.event.repository.name }}_branch.json
176187
label: coverage-branch
177-
message: ${{ steps.oneimlx-shared.outputs.coverage-branch }}%
178-
valColorRange: ${{ steps.oneimlx-shared.outputs.coverage-branch }}
188+
message: ${{ steps.coverage.outputs.branch }}%
189+
valColorRange: ${{ steps.coverage.outputs.branch }}
179190
maxColorRange: 100
180191
minColorRange: 0

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ This repository contains the shared components for our cross-platform frameworks
55
[![NuGet](https://img.shields.io/nuget/vpre/OneImlx.Test?label=OneImlx.Test)](https://www.nuget.org/packages/OneImlx.Test)
66

77
## Status
8-
[![Cross-Platform Build and Test](https://github.com/perpetualintelligence/shared/actions/workflows/build-test-cross.yml/badge.svg)](https://github.com/perpetualintelligence/shared/actions/workflows/build-test-cross-manual.yml)
9-
[![Push Build and Test](https://github.com/perpetualintelligence/shared/actions/workflows/build-test-push.yml/badge.svg)](https://github.com/perpetualintelligence/shared/actions/workflows/build-test-push.yml)
8+
[![build-test-cross](https://github.com/perpetualintelligence/shared/actions/workflows/build-test-cross.yml/badge.svg)](https://github.com/perpetualintelligence/shared/actions/workflows/build-test-cross.yml)
9+
[![build-test-push](https://github.com/perpetualintelligence/shared/actions/workflows/build-test-push.yml/badge.svg)](https://github.com/perpetualintelligence/shared/actions/workflows/build-test-push.yml)
1010

1111
![coverage-line](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/perpetualintelligencegit/141903832ee52f1e9e7913300a92d507/raw/coverage_shared_line.json)
1212
![coverage-branch](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/perpetualintelligencegit/141903832ee52f1e9e7913300a92d507/raw/coverage_shared_branch.json)

Shared.All.Solution.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
</Folder>
1414
<Folder Name="/test/">
1515
<Project Path="test/OneImlx.Shared.Tests/OneImlx.Shared.Tests.csproj" />
16+
<Project Path="test/OneImlx.Test.Tests/OneImlx.Test.Tests.csproj" Id="e9609456-eb72-4575-84bf-18dc91bd4883" />
1617
</Folder>
1718
</Solution>

build/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
# Build
22

33
## Local Machine
4-
Follow the steps to set up the `pi-cli` repository on your local development machine.
4+
Follow the steps to set up the `shared` repository on your local development machine.
55

6-
1. Download and install [Visual Studio 2022](https://visualstudio.microsoft.com/vs/)
7-
2. Clone the [protocols](https://github.com/perpetualintelligence/protocols) GitHub repo
6+
1. Download and install [Visual Studio 2026](https://visualstudio.microsoft.com/vs/)
7+
2. Clone the [shared](https://github.com/perpetualintelligence/shared) GitHub repo
88
3. Set PI_CI_REFERENCE environment variable to `cross`
99

1010
## CICD
1111
This workflow folder contains the build and deployment pipelines for generating and publishing [Nuget](https://www.nuget.org/profiles/perpetualintelligencellc) and [GitHub](https://github.com/orgs/perpetualintelligence/packages?repo_name=data) packages.
1212

13-
- *build-test-cross-manual*: The manual action that builds and tests the code changes on Windows, Linux and macOS.
14-
- *build-test-publish*: The automated action that publishes the packages to [Nuget](https://www.nuget.org/profiles/perpetualintelligencellc) and [GitHub](https://github.com/orgs/perpetualintelligence/packages?repo_name=data), see [releases](https://github.com/perpetualintelligence/cli/releases)
13+
- *build-test-cross*: The manual action that builds and tests the code changes on Windows, Linux and macOS.
14+
- *build-test-push*: The automated action that publishes the packages to [Nuget](https://www.nuget.org/profiles/perpetualintelligencellc) and [GitHub](https://github.com/orgs/perpetualintelligence/packages?repo_name=data), see [releases](https://github.com/perpetualintelligence/shared/releases)
1515
- *delete-packages*: The automated action cleans the packages every week and keeps the latest working version. For stable versions, refer to [Nuget](https://www.nuget.org/profiles/perpetualintelligencellc) packages.
1616

17-
> ***Note: The `build-test-publish` release to Nuget pipeline triggers a deployment approval.***
17+
> ***Note: The `build-test-push` release to Nuget pipeline triggers a deployment approval.***
1818
1919
## Versioning
2020
All packages follow [sematic](https://semver.org/) versioning schemes. The env file *package_version.env* defines the package versions.
2121

2222
## Project Dependencies
23-
The *PI_CI_REFERENCE* environment variable defines how *.csproj* references the dependencies for CI and local development. It supportes the following values:
23+
The *PI_CI_REFERENCE* environment variable defines how *.csproj* references the dependencies for CI and local development. It supports the following values:
2424
- *local*: Project references for local development within the same repo
2525
- *cross*: Project references for local development across repos
2626
- *package*: Package references for CI/CD and deployment
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright © 2019-2026 Perpetual Intelligence L.L.C. All rights reserved.
2+
// For license, terms, and data policies, go to:
3+
// https://terms.perpetualintelligence.com/articles/intro.html
4+
5+
using FluentAssertions;
6+
7+
namespace OneImlx.Test.Extentions
8+
{
9+
/// <summary>
10+
/// <see cref="object"/> extension methods for testing.
11+
/// </summary>
12+
public static class ObjectExtensions
13+
{
14+
/// <summary>
15+
/// Asserts that the source object is not null and returns the source object for chaining.
16+
/// </summary>
17+
/// <typeparam name="T">The type of the source object.</typeparam>
18+
/// <param name="source">The source object to check for null.</param>
19+
/// <returns>The source object if it is not null.</returns>
20+
public static T NotNull<T>(this T? source)
21+
{
22+
source.Should().NotBeNull();
23+
return source;
24+
}
25+
}
26+
}

src/OneImlx.Test/FluentAssertions/AssemblyFluentAssertions.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ public static AndConstraint<AssemblyAssertions> HaveTypesInRootNamespace(this As
2929
{
3030
var assembly = assertions.Subject;
3131
var actualNamespace = assembly.GetName().Name ?? throw new InvalidOperationException("Assembly name null");
32-
actualNamespace.Should().Be(rootNamespace, $"Assembly '{assembly.GetName().Name}' should have root namespace '{rootNamespace}'");
32+
if (actualNamespace != rootNamespace)
33+
{
34+
throw new AssertionFailedException($"Assembly '{assembly.GetName().Name}' should have root namespace '{rootNamespace}'.");
35+
}
3336

3437
var types = assembly.GetTypes().Where(e => !IsCompilerGenerated(e));
3538
var invalidTypes = types.Where(e =>

test/OneImlx.Shared.Tests/AssemblyTests.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
/*
2-
Copyright (c) 2023 Perpetual Intelligence L.L.C. All Rights Reserved.
3-
4-
For license, terms, and data policies, go to:
5-
https://terms.perpetualintelligence.com/articles/intro.html
6-
*/
1+
// Copyright © 2019-2026 Perpetual Intelligence L.L.C. All rights reserved.
2+
// For license, terms, and data policies, go to:
3+
// https://terms.perpetualintelligence.com/articles/intro.html
74

85
using FluentAssertions;
96
using OneImlx.Test.FluentAssertions;

0 commit comments

Comments
 (0)