mirror of
https://github.com/ivuorinen/actions.git
synced 2026-03-02 16:53:57 +00:00
* fix(deps): replace step-security/retry with nick-fields/retry * chore(deps): update github action sha pins via pinact * refactor: remove common-retry references from tests and validators * chore: simplify description fallback and update action count * docs: remove hardcoded test counts from memory and docs Replace exact "769 tests" references with qualitative language so these files don't go stale as test count grows.
249 lines
8.2 KiB
YAML
249 lines
8.2 KiB
YAML
# yaml-language-server: $schema=https://json.schemastore.org/github-action.json
|
|
# permissions:
|
|
# - packages: write # Required for publishing to GitHub Packages
|
|
# - contents: read # Required for checking out repository
|
|
---
|
|
name: C# Publish
|
|
description: 'Publishes a C# project to GitHub Packages.'
|
|
author: 'Ismo Vuorinen'
|
|
|
|
branding:
|
|
icon: package
|
|
color: blue
|
|
|
|
inputs:
|
|
dotnet-version:
|
|
description: 'Version of .NET SDK to use.'
|
|
required: false
|
|
namespace:
|
|
description: 'GitHub namespace for the package.'
|
|
required: true
|
|
default: 'ivuorinen'
|
|
token:
|
|
description: 'GitHub token with package write permissions'
|
|
required: false
|
|
max-retries:
|
|
description: 'Maximum number of retry attempts for dependency restoration'
|
|
required: false
|
|
default: '3'
|
|
|
|
outputs:
|
|
publish_status:
|
|
description: 'Overall publish status (success/failure)'
|
|
value: ${{ steps.set-status.outputs.status }}
|
|
package_version:
|
|
description: 'Version of the published package'
|
|
value: ${{ steps.extract-version.outputs.version }}
|
|
package_url:
|
|
description: 'URL of the published package'
|
|
value: ${{ steps.publish-package.outputs.package_url }}
|
|
|
|
runs:
|
|
using: composite
|
|
steps:
|
|
- name: Mask Secrets
|
|
shell: sh
|
|
env:
|
|
API_KEY: ${{ inputs.token || github.token }}
|
|
run: |
|
|
echo "::add-mask::$API_KEY"
|
|
|
|
- name: Checkout Repository
|
|
uses: actions/checkout@71cf2267d89c5cb81562390fa70a37fa40b1305e # v6-beta
|
|
with:
|
|
token: ${{ inputs.token || github.token }}
|
|
|
|
- name: Validate Inputs
|
|
id: validate
|
|
uses: ivuorinen/actions/validate-inputs@5cc7373a22402ee8985376bc713f00e09b5b2edb
|
|
with:
|
|
action-type: 'csharp-publish'
|
|
token: ${{ inputs.token }}
|
|
namespace: ${{ inputs.namespace }}
|
|
dotnet-version: ${{ inputs.dotnet-version }}
|
|
|
|
- name: Detect .NET SDK Version
|
|
id: detect-dotnet-version
|
|
shell: sh
|
|
env:
|
|
DEFAULT_VERSION: '7.0'
|
|
run: |
|
|
set -eu
|
|
|
|
# Function to validate version format
|
|
validate_version() {
|
|
version=$1
|
|
case "$version" in
|
|
[0-9]* | [0-9]*\.[0-9]* | [0-9]*\.[0-9]*\.[0-9]*)
|
|
return 0
|
|
;;
|
|
*)
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Function to clean version string
|
|
clean_version() {
|
|
printf '%s' "$1" | sed 's/^[vV]//' | tr -d ' \n\r'
|
|
}
|
|
|
|
detected_version=""
|
|
|
|
# Parse .tool-versions file
|
|
if [ -f .tool-versions ]; then
|
|
echo "Checking .tool-versions for dotnet..." >&2
|
|
version=$(awk '/^dotnet[[:space:]]/ {gsub(/#.*/, ""); print $2; exit}' .tool-versions 2>/dev/null || echo "")
|
|
if [ -n "$version" ]; then
|
|
version=$(clean_version "$version")
|
|
if validate_version "$version"; then
|
|
echo "Found .NET version in .tool-versions: $version" >&2
|
|
detected_version="$version"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Parse Dockerfile
|
|
if [ -z "$detected_version" ] && [ -f Dockerfile ]; then
|
|
echo "Checking Dockerfile for dotnet..." >&2
|
|
version=$(grep -iF "FROM" Dockerfile | grep -F "dotnet:" | head -1 | \
|
|
sed -n -E "s/.*dotnet:([0-9]+(\.[0-9]+)*)(-[^:]*)?.*/\1/p" || echo "")
|
|
if [ -n "$version" ]; then
|
|
version=$(clean_version "$version")
|
|
if validate_version "$version"; then
|
|
echo "Found .NET version in Dockerfile: $version" >&2
|
|
detected_version="$version"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Parse devcontainer.json
|
|
if [ -z "$detected_version" ] && [ -f .devcontainer/devcontainer.json ]; then
|
|
echo "Checking devcontainer.json for dotnet..." >&2
|
|
if command -v jq >/dev/null 2>&1; then
|
|
version=$(jq -r '.image // empty' .devcontainer/devcontainer.json 2>/dev/null | sed -n -E "s/.*dotnet:([0-9]+(\.[0-9]+)*)(-[^:]*)?.*/\1/p" || echo "")
|
|
if [ -n "$version" ]; then
|
|
version=$(clean_version "$version")
|
|
if validate_version "$version"; then
|
|
echo "Found .NET version in devcontainer: $version" >&2
|
|
detected_version="$version"
|
|
fi
|
|
fi
|
|
else
|
|
echo "jq not found; skipping devcontainer.json parsing" >&2
|
|
fi
|
|
fi
|
|
|
|
# Parse global.json
|
|
if [ -z "$detected_version" ] && [ -f global.json ]; then
|
|
echo "Checking global.json..." >&2
|
|
if command -v jq >/dev/null 2>&1; then
|
|
version=$(jq -r '.sdk.version // empty' global.json 2>/dev/null || echo "")
|
|
if [ -n "$version" ]; then
|
|
version=$(clean_version "$version")
|
|
if validate_version "$version"; then
|
|
echo "Found .NET version in global.json: $version" >&2
|
|
detected_version="$version"
|
|
fi
|
|
fi
|
|
else
|
|
echo "jq not found; skipping global.json parsing" >&2
|
|
fi
|
|
fi
|
|
|
|
# Use default version if nothing detected
|
|
if [ -z "$detected_version" ]; then
|
|
detected_version="$DEFAULT_VERSION"
|
|
echo "Using default .NET version: $detected_version" >&2
|
|
fi
|
|
|
|
# Set output
|
|
printf 'detected-version=%s\n' "$detected_version" >> "$GITHUB_OUTPUT"
|
|
echo "Final detected .NET version: $detected_version" >&2
|
|
|
|
- name: Setup .NET SDK
|
|
uses: actions/setup-dotnet@baa11fbfe1d6520db94683bd5c7a3818018e4309 # v5.1.0
|
|
with:
|
|
dotnet-version: ${{ inputs.dotnet-version || steps.detect-dotnet-version.outputs.detected-version }}
|
|
cache: true
|
|
cache-dependency-path: '**/packages.lock.json'
|
|
|
|
- name: Restore Dependencies
|
|
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
|
|
with:
|
|
timeout_minutes: 10
|
|
max_attempts: ${{ inputs.max-retries }}
|
|
command: |
|
|
echo "Restoring .NET dependencies..."
|
|
dotnet restore --verbosity normal
|
|
|
|
- name: Build Solution
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
|
|
dotnet build --configuration Release --no-restore
|
|
|
|
- name: Pack Solution
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
|
|
dotnet pack --configuration Release --no-build --no-restore --output ./artifacts
|
|
|
|
- name: Extract Package Version
|
|
id: extract-version
|
|
shell: sh
|
|
run: |
|
|
set -eu
|
|
|
|
# Find the newest .nupkg file by modification time and extract version
|
|
PACKAGE_FILE=$(find ./artifacts -name "*.nupkg" -type f -printf '%T@ %p\n' | sort -rn | head -n 1 | cut -d' ' -f2-)
|
|
if [ -n "$PACKAGE_FILE" ]; then
|
|
# Extract version from filename (assumes standard naming: PackageName.Version.nupkg)
|
|
VERSION=$(basename "$PACKAGE_FILE" .nupkg | sed 's/.*\.\([0-9]\+\.[0-9]\+\.[0-9]\+.*\)$/\1/')
|
|
printf '%s\n' "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
printf '%s\n' "package_file=$PACKAGE_FILE" >> "$GITHUB_OUTPUT"
|
|
else
|
|
printf '%s\n' "version=unknown" >> "$GITHUB_OUTPUT"
|
|
printf '%s\n' "package_file=" >> "$GITHUB_OUTPUT"
|
|
fi
|
|
|
|
- name: Publish Package
|
|
id: publish-package
|
|
shell: sh
|
|
env:
|
|
API_KEY: ${{ inputs.token || github.token }}
|
|
NAMESPACE: ${{ inputs.namespace }}
|
|
run: |
|
|
set -eu
|
|
|
|
PACKAGE_URL="https://github.com/$NAMESPACE/packages/nuget"
|
|
printf '%s\n' "package_url=$PACKAGE_URL" >> "$GITHUB_OUTPUT"
|
|
|
|
# First attempt
|
|
if ! dotnet nuget push ./artifacts/*.nupkg \
|
|
--api-key "$API_KEY" \
|
|
--source "https://nuget.pkg.github.com/$NAMESPACE/index.json" \
|
|
--skip-duplicate \
|
|
--no-symbols; then
|
|
|
|
echo "::warning::First publish attempt failed, retrying after 5 seconds..."
|
|
sleep 5
|
|
|
|
dotnet nuget push ./artifacts/*.nupkg \
|
|
--api-key "$API_KEY" \
|
|
--source "https://nuget.pkg.github.com/$NAMESPACE/index.json" \
|
|
--skip-duplicate \
|
|
--no-symbols
|
|
fi
|
|
|
|
- name: Set publish status output
|
|
if: always()
|
|
id: set-status
|
|
shell: sh
|
|
env:
|
|
PUBLISH_STATUS: ${{ steps.publish-package.outcome == 'success' && 'success' || 'failure' }}
|
|
run: |-
|
|
printf '%s\n' "status=$PUBLISH_STATUS" >> "$GITHUB_OUTPUT"
|