mirror of
https://github.com/ivuorinen/actions.git
synced 2026-01-26 03:23:59 +00:00
Remove the 'Restore Complete' step that always printed 'Cache hit - skipping dotnet restore' even though restore always runs via the retry action. The message was misleading because: - Dependencies are always restored via step-security/retry - The message claimed restore was skipped, which was false - The step served no actual purpose The 'Restore Dependencies' step already provides appropriate output during execution, making this step redundant and confusing.
249 lines
8.3 KiB
YAML
249 lines
8.3 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: bash
|
|
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@0fa9a68f07a1260b321f814202658a6089a43d42
|
|
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@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0
|
|
with:
|
|
dotnet-version: ${{ inputs.dotnet-version || steps.detect-dotnet-version.outputs.detected-version }}
|
|
cache: true
|
|
cache-dependency-path: '**/*.csproj'
|
|
|
|
- name: Restore Dependencies
|
|
uses: step-security/retry@e1d59ce1f574b32f0915e3a8df055cfe9f99be5d # v3
|
|
with:
|
|
timeout_minutes: 10
|
|
max_attempts: ${{ inputs.max-retries }}
|
|
command: |
|
|
echo "Restoring .NET dependencies..."
|
|
dotnet restore --verbosity normal
|
|
|
|
- name: Build Solution
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
dotnet build --configuration Release --no-restore
|
|
|
|
- name: Pack Solution
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
dotnet pack --configuration Release --no-build --no-restore --output ./artifacts
|
|
|
|
- name: Extract Package Version
|
|
id: extract-version
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
# 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: bash
|
|
env:
|
|
API_KEY: ${{ inputs.token || github.token }}
|
|
NAMESPACE: ${{ inputs.namespace }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
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: bash
|
|
env:
|
|
PUBLISH_STATUS: ${{ steps.publish-package.outcome == 'success' && 'success' || 'failure' }}
|
|
run: |-
|
|
printf '%s\n' "status=$PUBLISH_STATUS" >> "$GITHUB_OUTPUT"
|