Skip to content

Commit b9df3f6

Browse files
author
Jani Giannoudis
committed
initial country regulation template — NuGet packaging, CI/CD workflows and regulation skeleton
0 parents  commit b9df3f6

33 files changed

+1329
-0
lines changed

.github/workflows/ci.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
packages: read
12+
13+
env:
14+
DOTNET_VERSION: '10.0.x'
15+
16+
jobs:
17+
build:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Read version
23+
id: version
24+
run: |
25+
VERSION=$(grep -oP '(?<=<Version>)[^<]+' Directory.Build.props)
26+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
27+
echo "Version: ${VERSION}"
28+
29+
- name: Setup .NET
30+
uses: actions/setup-dotnet@v4
31+
with:
32+
dotnet-version: ${{ env.DOTNET_VERSION }}
33+
34+
- name: Configure GitHub Packages
35+
run: |
36+
# Remove local dev source (not available in CI)
37+
dotnet nuget remove source PayrollEngine 2>/dev/null || true
38+
dotnet nuget add source \
39+
"https://nuget.pkg.github.com/Payroll-Engine/index.json" \
40+
--name github \
41+
--username github-actions \
42+
--password ${{ secrets.GITHUB_TOKEN }} \
43+
--store-password-in-clear-text
44+
45+
- name: Restore
46+
run: dotnet restore
47+
48+
- name: Build
49+
run: dotnet build --configuration Release --no-restore
50+
51+
- name: Pack
52+
run: dotnet pack --configuration Release --no-build --output ./nupkgs
53+
54+
- name: List packages
55+
run: ls -la ./nupkgs/

.github/workflows/release.yml

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
name: Release
2+
3+
# Triggered automatically when Directory.Build.props changes on main.
4+
# Skips silently if the version ends with ".dev" or the tag already exists.
5+
# Can also be triggered manually via workflow_dispatch — version is always
6+
# read from Directory.Build.props, never entered as an input.
7+
#
8+
# Required secret: PAT_DISPATCH
9+
# Classic PAT with scopes: repo, workflow, write:packages, read:packages
10+
# Settings → Secrets → Actions → New repository secret
11+
12+
on:
13+
push:
14+
branches: [main]
15+
paths:
16+
- Directory.Build.props
17+
workflow_dispatch: {}
18+
19+
permissions:
20+
contents: write
21+
packages: write
22+
23+
env:
24+
DOTNET_VERSION: '10.0.x'
25+
26+
jobs:
27+
release:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/checkout@v4
31+
with:
32+
token: ${{ secrets.PAT_DISPATCH }}
33+
fetch-depth: 0
34+
35+
# ── Read version from Directory.Build.props ──────────────────────────
36+
- name: Read version
37+
id: version
38+
run: |
39+
VERSION=$(grep -oP '(?<=<Version>)[^<]+' Directory.Build.props)
40+
echo "version=${VERSION}" >> $GITHUB_OUTPUT
41+
echo "Version: ${VERSION}"
42+
43+
if [[ "${VERSION}" == *".dev"* ]]; then
44+
echo "is_dev=true" >> $GITHUB_OUTPUT
45+
echo "⏭️ Development version — skipping release"
46+
else
47+
echo "is_dev=false" >> $GITHUB_OUTPUT
48+
if [[ "${VERSION}" == *-* ]]; then
49+
echo "is_prerelease=true" >> $GITHUB_OUTPUT
50+
else
51+
echo "is_prerelease=false" >> $GITHUB_OUTPUT
52+
fi
53+
fi
54+
55+
# ── Version guard — idempotent skip if tag already exists ────────────
56+
- name: Version guard
57+
if: steps.version.outputs.is_dev != 'true'
58+
id: guard
59+
uses: actions/github-script@v7
60+
with:
61+
github-token: ${{ secrets.PAT_DISPATCH }}
62+
script: |
63+
const version = '${{ steps.version.outputs.version }}';
64+
const tag = `v${version}`;
65+
const owner = context.repo.owner;
66+
const repo = context.repo.repo;
67+
68+
// Check Git tag
69+
try {
70+
await github.rest.git.getRef({ owner, repo, ref: `tags/${tag}` });
71+
console.log(`⏭️ Tag '${tag}' already exists — skipping release`);
72+
core.setOutput('skip', 'true');
73+
return;
74+
} catch (e) {
75+
if (e.status !== 404) throw e;
76+
}
77+
78+
// Check GitHub Release
79+
try {
80+
await github.rest.repos.getReleaseByTag({ owner, repo, tag });
81+
console.log(`⏭️ Release '${tag}' already exists — skipping release`);
82+
core.setOutput('skip', 'true');
83+
return;
84+
} catch (e) {
85+
if (e.status !== 404) throw e;
86+
}
87+
88+
console.log(`✅ Version ${version} is clean — proceeding`);
89+
core.setOutput('skip', 'false');
90+
91+
# ── Sync regulation-package.json version ─────────────────────────────
92+
- name: Sync regulation-package.json
93+
if: steps.version.outputs.is_dev != 'true' && steps.guard.outputs.skip != 'true'
94+
run: |
95+
VERSION="${{ steps.version.outputs.version }}"
96+
if [ -f regulation-package.json ]; then
97+
if command -v jq &>/dev/null; then
98+
jq --arg v "$VERSION" '.version = $v' regulation-package.json \
99+
> regulation-package.tmp.json && mv regulation-package.tmp.json regulation-package.json
100+
echo "✅ regulation-package.json version set to ${VERSION}"
101+
else
102+
sed -i "s|\"version\": \"[^\"]*\"|\"version\": \"${VERSION}\"|" regulation-package.json
103+
echo "✅ regulation-package.json version set to ${VERSION} (sed)"
104+
fi
105+
fi
106+
107+
# ── Build ─────────────────────────────────────────────────────────────
108+
- name: Setup .NET
109+
if: steps.version.outputs.is_dev != 'true' && steps.guard.outputs.skip != 'true'
110+
uses: actions/setup-dotnet@v4
111+
with:
112+
dotnet-version: ${{ env.DOTNET_VERSION }}
113+
114+
- name: Configure GitHub Packages
115+
if: steps.version.outputs.is_dev != 'true' && steps.guard.outputs.skip != 'true'
116+
run: |
117+
# Remove local dev source (not available in CI)
118+
dotnet nuget remove source PayrollEngine 2>/dev/null || true
119+
dotnet nuget add source \
120+
"https://nuget.pkg.github.com/Payroll-Engine/index.json" \
121+
--name github \
122+
--username github-actions \
123+
--password ${{ secrets.PAT_DISPATCH }} \
124+
--store-password-in-clear-text
125+
126+
- name: Restore
127+
if: steps.version.outputs.is_dev != 'true' && steps.guard.outputs.skip != 'true'
128+
run: dotnet restore
129+
130+
- name: Build
131+
if: steps.version.outputs.is_dev != 'true' && steps.guard.outputs.skip != 'true'
132+
run: dotnet build --configuration Release --no-restore
133+
134+
- name: Pack
135+
if: steps.version.outputs.is_dev != 'true' && steps.guard.outputs.skip != 'true'
136+
run: dotnet pack --configuration Release --no-build --output ./nupkgs
137+
138+
# ── Publish to GitHub Packages ────────────────────────────────────────
139+
# Package visibility inherits from the repository:
140+
# public repo → public package (accessible without authentication)
141+
# private repo → private package (requires read:packages PAT)
142+
- name: Publish to GitHub Packages
143+
if: steps.version.outputs.is_dev != 'true' && steps.guard.outputs.skip != 'true'
144+
run: |
145+
dotnet nuget push ./nupkgs/*.nupkg \
146+
--source "https://nuget.pkg.github.com/Payroll-Engine/index.json" \
147+
--api-key ${{ secrets.GITHUB_TOKEN }} \
148+
--skip-duplicate
149+
150+
# ── Create GitHub Release with .nupkg as asset ───────────────────────
151+
# The .nupkg asset enables direct URL installation via:
152+
# InstallRegulationPackage <release-asset-url> <tenant>
153+
- name: Create GitHub Release
154+
if: steps.version.outputs.is_dev != 'true' && steps.guard.outputs.skip != 'true'
155+
uses: softprops/action-gh-release@v2
156+
with:
157+
tag_name: v${{ steps.version.outputs.version }}
158+
name: v${{ steps.version.outputs.version }}
159+
prerelease: ${{ steps.version.outputs.is_prerelease }}
160+
generate_release_notes: true
161+
files: ./nupkgs/*.nupkg

.gitignore

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
## Ignore Visual Studio temporary files, build results, and
2+
## files generated by popular Visual Studio add-ons.
3+
##
4+
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5+
6+
# User-specific files
7+
*.rsuser
8+
*.suo
9+
*.user
10+
*.userosscache
11+
*.sln.docstates
12+
13+
# User-specific files (MonoDevelop/Xamarin Studio)
14+
*.userprefs
15+
16+
# Build results
17+
[Dd]ebug/
18+
[Dd]ebugPublic/
19+
[Rr]elease/
20+
[Rr]eleases/
21+
x64/
22+
x86/
23+
[Aa][Rr][Mm]/
24+
[Aa][Rr][Mm]64/
25+
bld/
26+
[Bb]in/
27+
[Oo]bj/
28+
[Ll]og/
29+
30+
# Visual Studio 2015/2017 cache/options directory
31+
.vs/
32+
33+
# Visual Studio 2017 auto generated files
34+
Generated\ Files/
35+
36+
# MSTest test Results
37+
[Tt]est[Rr]esult*/
38+
[Bb]uild[Ll]og.*
39+
40+
# NUNIT
41+
*.VisualState.xml
42+
TestResult.xml
43+
44+
# .NET Core
45+
project.lock.json
46+
project.fragment.lock.json
47+
artifacts/
48+
49+
# StyleCop
50+
StyleCopReport.xml
51+
52+
# Files built by Visual Studio
53+
*_i.c
54+
*_p.c
55+
*_h.h
56+
*.ilk
57+
*.meta
58+
*.obj
59+
*.iobj
60+
*.pch
61+
*.pdb
62+
*.ipdb
63+
*.pgc
64+
*.pgd
65+
*.rsp
66+
*.sbr
67+
*.tlb
68+
*.tli
69+
*.tlh
70+
*.tmp
71+
*.tmp_proj
72+
*_wpftmp.csproj
73+
*.log
74+
*.vspscc
75+
*.vssscc
76+
.builds
77+
*.pidb
78+
*.svclog
79+
*.scc
80+
81+
# Visual C++ cache files
82+
ipch/
83+
*.aps
84+
*.ncb
85+
*.opendb
86+
*.opensdf
87+
*.sdf
88+
*.cachefile
89+
*.VC.db
90+
*.VC.VC.opendb
91+
92+
# ReSharper
93+
_ReSharper*/
94+
*.[Rr]e[Ss]harper
95+
*.DotSettings.user
96+
97+
# DotCover
98+
*.dotCover
99+
100+
# Visual Studio code coverage
101+
*.coverage
102+
*.coveragexml
103+
104+
# NuGet
105+
*.nupkg
106+
nupkgs/
107+
**/[Pp]ackages/*
108+
!**/[Pp]ackages/build/
109+
*.nuget.props
110+
*.nuget.targets
111+
112+
# JetBrains Rider
113+
.idea/
114+
*.sln.iml
115+
116+
# Python
117+
__pycache__/
118+
*.pyc
119+
120+
# MSBuild logs
121+
*.binlog
122+
123+
# NDepend
124+
/NDependOut*/
125+
126+
# Misc
127+
/**/DROP/
128+
/**/TEMP/
129+
/**/packages/
130+
/**/bin/
131+
/**/obj/

Delete.Tests.pecmd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### removes test payroll and payrun without deleting the regulation ###
2+
PayrunDelete {CC}.Payrun /tenantidentifier:{CC}.{RegulationName} /trydelete
3+
PayrollDelete {CC}.Payroll /tenantidentifier:{CC}.{RegulationName} /trydelete

Delete.pecmd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TenantDelete {CC}.{RegulationName} /trydelete

Directory.Build.props

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<Project>
2+
3+
<PropertyGroup>
4+
<TargetFramework>net10.0</TargetFramework>
5+
<Version>1.0.0-beta.dev</Version>
6+
<FileVersion>1.0.0</FileVersion>
7+
<InformationalVersion></InformationalVersion>
8+
<Authors>{Provider}</Authors>
9+
<Company>{Provider}</Company>
10+
<Copyright>© 2026 {Provider}</Copyright>
11+
<Product>Payroll Engine Regulation {CC}.{RegulationName}</Product>
12+
<PackageProjectUrl>https://payrollengine.org/</PackageProjectUrl>
13+
<RepositoryUrl>https://github.com/{Provider}/Regulation.{CC}.{RegulationName}.git</RepositoryUrl>
14+
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
15+
</PropertyGroup>
16+
17+
<PropertyGroup>
18+
<!-- Disable NuGet vulnerability audit — regulation packages have no runtime dependencies -->
19+
<NuGetAudit>false</NuGetAudit>
20+
</PropertyGroup>
21+
22+
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
23+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
24+
<WarningsAsErrors />
25+
<NoWarn>1701;1702;8034;AD0001</NoWarn>
26+
</PropertyGroup>
27+
28+
</Project>

0 commit comments

Comments
 (0)