Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reuseable workflow #390

Merged
merged 1 commit into from
Apr 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/update-dotnet-sdk-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: update-dotnet-sdk-test

on:
workflow_dispatch:

permissions:
contents: read
pull-requests: read

jobs:
update-sdk:
uses: martincostello/update-dotnet-sdk/.github/workflows/update-dotnet-sdk.yml@reusable-workflow
permissions:
contents: write
pull-requests: write
with:
global-json-file: './_global.json'
labels: dependencies
secrets:
repo-token: ${{ secrets.GITHUB_TOKEN }}

print-outputs:
name: Print outcome
needs: update-sdk
if: ${{ needs.update-sdk.outputs.sdk-updated == 'true' }}
runs-on: ubuntu-latest

steps:

- name: Print update details
run: |
echo "PR number: ${{ steps.update.outputs.pull-request-number }}"
echo "PR URL: ${{ steps.update.outputs.pull-request-html-url }}"
echo "SDK version: ${{ steps.update.outputs.sdk-version }}"
224 changes: 205 additions & 19 deletions .github/workflows/update-dotnet-sdk.yml
Original file line number Diff line number Diff line change
@@ -1,37 +1,223 @@
name: update-dotnet-sdk

on:
workflow_dispatch:
workflow_call:
inputs:
branch-name:
description: 'The optional Git branch name to use.'
required: false
type: string
default: ''
channel:
description: 'The optional .NET release channel to download the SDK for (2.1, 3.1, 5.0, etc.).'
required: false
type: string
default: ''
commit-message:
description: 'The optional Git commit message to use.'
required: false
type: string
default: ''
global-json-file:
description: 'The optional path to the global.json file to update.'
required: false
type: string
default: './global.json'
labels:
description: 'The optional comma-separated label(s) to apply to Pull Requests generated by the action.'
required: false
type: string
default: ''
update-nuget-packages:
description: 'If true, the action will update any Microsoft-published NuGet packages to their latest versions for the specified .NET release channel.'
required: false
type: boolean
default: true
include-nuget-packages:
description: 'A comma-separated list of NuGet package IDs (or substrings) to update, if update-nuget-packages is true.'
required: false
type: string
default: 'Microsoft.AspNetCore.,Microsoft.EntityFrameworkCore.,Microsoft.Extensions.,System.Text.Json'
user-email:
description: 'The optional email address to use for the Git commit.'
required: false
type: string
default: 'github-actions[bot]@users.noreply.github.com'
user-name:
description: 'The optional user name to use for the Git commit.'
required: false
type: string
default: 'github-actions[bot]'
dry-run:
description: 'If true, the action will not push changes to GitHub.'
required: false
type: boolean
default: false
runs-on:
description: 'The GitHub Actions runner to use.'
required: false
type: string
default: 'ubuntu-latest'
secrets:
repo-token:
description: 'The GitHub access token to use to clone the repository, push changes and create a Pull Request for any SDK update.'
required: true

permissions:
contents: read
pull-requests: read
env:
TERM: xterm

jobs:
update-sdk:
runs-on: ubuntu-latest

update-dotnet-sdk:

name: Update .NET SDK
runs-on: ${{ inputs.runs-on }}
# We don't want anyone forking this repository to also run this workflow
if: ${{ github.event.repository.fork == false }}

permissions:
contents: write
pull-requests: write
outputs:
pull-request-html-url: ${{ steps.update-dotnet-sdk.outputs.pull-request-html-url }}
pull-request-number: ${{ steps.update-dotnet-sdk.outputs.pull-request-number }}
sdk-updated: ${{ steps.update-dotnet-sdk.outputs.sdk-updated }}
sdk-version: ${{ steps.update-dotnet-sdk.outputs.sdk-version }}

steps:

# Checkout the repository so the global.json file can be inspected and
# updated if a new patch version of the SDK is available. The token is
# used so that the workflow can push any changes back to the repository
# and that pushes as that user trigger any CI workflows that may trigger
# on push, such as if any NuGet packages are updated after the PR is opened.
- name: Checkout code
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
with:
token: ${{ secrets.repo-token }}

# Run the action to check if a new version of the .NET SDK is available
# for the same release channel as the SDK specified in global.json.
- name: Update .NET SDK
id: update
uses: ./
id: update-dotnet-sdk
uses: martincostello/update-dotnet-sdk@8d99db1db36692f0d5c5bf3ef91fb654c2d4e298 # v2.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
global-json-file: './_global.json'
labels: dependencies
branch-name: ${{ inputs.branch-name }}
channel: ${{ inputs.channel }}
commit-message: ${{ inputs.commit-message }}
dry-run: ${{ inputs.dry-run }}
global-json-file: ${{ inputs.global-json-file }}
labels: ${{ inputs.labels }}
repo-token: ${{ secrets.repo-token }}
user-email: ${{ inputs.user-email }}
user-name: ${{ inputs.user-name }}

- name: Print outputs
# If the action updated the .NET SDK, then install the .NET SDK and then
# run the dotnet-outdated global tool to update any Microsoft-published
# NuGet packages for that patch release of .NET to their latest versions too.
- name: Setup .NET SDK
uses: actions/setup-dotnet@607fce577a46308457984d59e4954e075820f10a # v3.0.3
if : ${{ inputs.update-nuget-packages && steps.update-dotnet-sdk.outputs.sdk-updated == 'true' }}
with:
global-json-file: ${{ inputs.global-json-file }}

- name: Update NuGet packages
if : ${{ inputs.update-nuget-packages && steps.update-dotnet-sdk.outputs.sdk-updated == 'true' }}
shell: pwsh
env:
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_NOLOGO: true
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION: 1
NUGET_XMLDOC_MODE: skip
run: |
echo "PR number: ${{ steps.update.outputs.pull-request-number }}"
echo "PR URL: ${{ steps.update.outputs.pull-request-html-url }}"
echo "SDK Updated? ${{ steps.update.outputs.sdk-updated }}"
echo "SDK version: ${{ steps.update.outputs.sdk-version }}"
$ErrorActionPreference = "Stop"

dotnet tool install --global dotnet-outdated-tool

$tempPath = [System.IO.Path]::GetTempPath()
$updatesPath = (Join-Path $tempPath "dotnet-outdated.json")

Write-Host "Checking for .NET NuGet package(s) to update..."

# The --version-lock Major option is used to only update packages
# to the latest patch version of the current major version.
# The --include flags are used to only update Microsoft-published
# NuGet packages that are typically published with a new patch
# release of .NET that accompanies a new .NET SDK release.
$eligblePackages = "${{ inputs.include-nuget-packages }}".Split(',')
$includePackages = $()

foreach ($package in $eligblePackages) {
$includePackages += "--include"
$includePackages += $package
}

dotnet outdated `
--upgrade `
--version-lock Major `
--output $updatesPath `
$includePackages

$dependencies = @()

# Determine the distinct set of package updates that were applied, if any.
if (Test-Path $updatesPath) {
$dependencies = `
Get-Content -Path $updatesPath | `
ConvertFrom-Json | `
Select-Object -ExpandProperty projects | `
Select-Object -ExpandProperty TargetFrameworks | `
Select-Object -ExpandProperty Dependencies | `
Sort-Object -Property Name -Unique
}

if ($dependencies.Count -gt 0) {
Write-Host "Found $($dependencies.Count) .NET NuGet package(s) to update." -ForegroundColor Green

$commitMessageLines = @()

# Generate the commit message in a way that contains metadata similar to the way
# commit messages from dependabot updates are generated so that the approve-and-merge
# workflow can parse the commits to determine which packages were updated so that
# it can determine whether or not it is appropriate to approve the PR and then
# automatically merge it if the required statuses for the pull request are successful.
if ($dependencies.Count -eq 1) {
$commitMessageLines += "Bump $($dependencies[0].Name) from $($dependencies[0].ResolvedVersion) to $($dependencies[0].LatestVersion)"
$commitMessageLines += ""
$commitMessageLines += "Bumps $($dependencies[0].Name) from $($dependencies[0].ResolvedVersion) to $($dependencies[0].LatestVersion)."
} else {
$commitMessageLines += "Bump .NET NuGet packages"
$commitMessageLines += ""
$commitMessageLines += "Bumps .NET dependencies to their latest versions for the .NET ${{ steps.update-dotnet-sdk.outputs.sdk-version }} SDK."
$commitMessageLines += ""
foreach ($dependency in $dependencies) {
$commitMessageLines += "Bumps $($dependency.Name) from $($dependency.ResolvedVersion) to $($dependency.LatestVersion)."
}
}

$commitMessageLines += ""
$commitMessageLines += "---"
$commitMessageLines += "updated-dependencies:"

foreach ($dependency in $dependencies) {
$commitMessageLines += "- dependency-name: $($dependency.Name)"
$commitMessageLines += " dependency-type: direct:production"
$commitMessageLines += " update-type: version-update:semver-$($dependency.UpgradeSeverity.ToLowerInvariant())"
}

$commitMessageLines += "..."
$commitMessageLines += ""
$commitMessageLines += ""

$commitMessage = $commitMessageLines -join "`n"

git config user.email "${{ inputs.user-email }}"
git config user.name "${{ inputs.user-name }}"

git add .
git commit -m $commitMessage
git push

Write-Host "Pushed update to $($dependencies.Count) NuGet package(s)." -ForegroundColor Green
}
else {
Write-Host "There are no .NET NuGet packages to update." -ForegroundColor Green
}