Skip to content

Follow Upstream

Follow Upstream #210

Workflow file for this run

name: Follow Upstream
on:
push:
branches: [ main, master ]
pull_request:
branches: [ '**', '!gh-pages', '!coverage' ]
types: [ opened, reopened, ready_for_review, synchronize ]
schedule:
- cron: '0 17 * * 0'
workflow_dispatch:
inputs:
defaults:
run:
shell: bash
jobs:
check:
name: Check Upstream
uses: StirlingLabs/Actions/.github/workflows/nugetCheckRelease.yaml@main
with:
upstream: 'microsoft/msquic'
rids: 'linux-x64 osx win-x64'
releasePrefix: 'v'
ignoreReleases: '2.2.1 2.0.4 1.9.0 1.1.8 1.0.3 1.8.0 1.7.0 1.6.0 1.5.0 1.4.0 1.1.6 1.3.0 1.1.4 1.2.0 1.1.3 1.1.2 1.1.0-138070 1.0.0-129524 0.9.2-draft-31'
nupkgName: 'StirlingLabs.MsQuic.Bindings.runtime.RID.openssl'
binaries:
name: Get Upstream Binaries
needs: [ check ]
if: needs.check.outputs.continue == 'true'
strategy:
fail-fast: false
max-parallel: 1
matrix:
release: ${{ fromJSON(needs.check.outputs.releases_needed_json) }}
runs-on: ubuntu-22.04
outputs:
continue: ${{ steps.download.outputs.continue }}
manifest: ${{ steps.download.outputs.manifest }}
matrixRid: ${{ steps.download.outputs.ridArray }}
readme: ${{ steps.ancillary.outputs.readme }}
icon: ${{ steps.ancillary.outputs.icon }}
steps:
- name: Get Libraries
id: download
env:
release: ${{ matrix.release }}
releasePrefix: ${{ needs.check.outputs.releasePrefix }}
releasesUrl: ${{ needs.check.outputs.releasesUrl }}
tagsUrl: ${{ needs.check.outputs.tagsUrl }}
rids: ${{ needs.check.outputs.rids }}
run: |
#
# Get info about the release being processed
echo "Processing $release"
if ! allReleasesJson="$( jq -c . <<< "$(curl -s "${releasesUrl}")" )" ; then
echo "‼️ Problem getting releases: ${allReleasesJson}"
fi
if ! releaseJson="$( jq -r ".[] | select(.tag_name==\"${releasePrefix}${release}\" )" <<< "$allReleasesJson" )" \
|| [[ "$releaseJson" == "" ]] ; then
echo "‼️ Problem getting release info for ${release}: ${releaseJson}"
fi
if ! gitBranch="$( jq -r ".target_commitish" <<< "$releaseJson" )" \
|| [[ "$gitBranch" == "" ]] ; then
echo "‼️ Problem getting branch: ${gitBranch}"
fi
if ! tagsJson="$( jq -c . <<< "$(curl -s "$tagsUrl")" )" ; then
echo "‼️ Problem getting tags: ${tagsJson}"
fi
if ! gitCommit="$( jq -r ".[] | select(.name==\"${releasePrefix}${release}\" ) | .commit.sha" <<< "$tagsJson")" \
|| [[ "$gitCommit" == "" ]] ; then
echo "‼️ Problem getting commit: ${gitCommit}"
fi
#
# Process this release
continue="false"
ridsAvailable="" && ridsAvailableComma=""
for rid in $rids ; do
echo " - $rid"
case "${rid}" in
linux-x64) platform="linux_x64" && upstreamFilename="libmsquic.so.$release" && ourFilename="libmsquic-openssl.so" ;;
osx) platform="macos_universal" && upstreamFilename="libmsquic.$release.dylib" && ourFilename="libmsquic-openssl.dylib" ;;
win-x64) platform="windows_x64" && upstreamFilename="msquic.dll" && ourFilename="msquic-openssl.dll" ;;
*) echo "Do not recognise ${rid}." && exit 1 ;;
esac
archive="msquic_${platform}_Release_openssl.zip"
if url="$(jq -r ".assets | .[] | select(.name==\"${archive}\") | .browser_download_url" <<< "$releaseJson")" ; then
if [ "$url" == "" ] ; then
echo " - ‼️ This release has no files for $rid."
continue
fi
echo "Downloading $url"
if wget --quiet "${url}" ; then
unzip "${archive}" -d "${platform}"
mkdir -p "${releasePrefix}${release}/${rid}"
finalFilename="${releasePrefix}${release}/${rid}/${ourFilename}"
mv "${platform}/bin/${upstreamFilename}" "${finalFilename}"
sudo chmod +r "${finalFilename}"
rm -Rf "${platform}" "${archive}"
else
echo " - ‼️ Problem downloading $url"
fi
ridsAvailable="${ridsAvailable}${ridsAvailableComma}{ \"rid\": \"${rid}\", \"location\": \"${finalFilename}\", \"filename\": \"${ourFilename}\" }"
ridsAvailableComma=", "
else
echo -e " - problem getting URL from $archive $releaseJson: $url"
fi
done
if [ "$ridsAvailable" != "" ] ; then
continue="true"
#shellcheck disable=SC2089
manifest="{ \"version\": \"${release}\", \"gitBranch\": \"${gitBranch}\", \"gitCommit\": \"${gitCommit}\", \"platforms\": [ $ridsAvailable ] }"
echo "$manifest" > manifest.json
else
continue=false
fi
#
# Outputs
echo "continue=${continue}" >> "$GITHUB_OUTPUT"
echo "manifest=${manifest}" >> "$GITHUB_OUTPUT"
- name: Upload Libraries
if: steps.download.outputs.continue == 'true'
uses: actions/upload-artifact@v3
with:
name: Libraries-${{ matrix.release }}
path: "./*"
- name: Get Source
if: steps.download.outputs.continue == 'true'
uses: actions/checkout@v3
- name: Identify Ancillaries
if: steps.download.outputs.continue == 'true'
id: ancillary
env:
readme: StirlingLabs.MsQuic.Bindings/README.md
icon: SL.png
manifest: ${{ steps.download.outputs.manifest }}
run: |
main() {
if [[ -s "${readme}" ]] ; then
echo "readme=${readme}" >> $GITHUB_OUTPUT
else
echo "README Not found at ${readme}"
fi
if [[ -s "${icon}" ]] ; then
echo "icon=${icon}" >> $GITHUB_OUTPUT
else
echo "Icon Not found at ${icon}"
fi
[[ -f manifest.json ]] && rm -f manifest.json
if checkJson "$platformJson" ; then
echo $manifest > manifest.json
echo "Wrote manifest.json"
fi
find .
}
function checkJson() {
local json="$1" ; local out
if ! out="$( echo "$json" | jq -c '.' )" ; then
echo "‼️ Error: Failed to verify json: $out" >&2
return 1
fi
}
main "$@" ; exit $?
- name: Upload Ancillaries
if: steps.download.outputs.continue == 'true'
uses: actions/upload-artifact@v3
with:
name: Ancillaries-${{ matrix.release }}
path: |
${{ steps.ancillary.outputs.readme }}
${{ steps.ancillary.outputs.icon }}
manifest.json
nupkg:
name: Publish NuPkg
needs: [ check, binaries ]
if: |
needs.check.outputs.continue == 'true' &&
needs.binaries.outputs.continue == 'true'
strategy:
fail-fast: true
max-parallel: 3
matrix:
version: ${{ fromJSON(needs.check.outputs.releases_needed_json) }}
rid: ${{ fromJSON(needs.check.outputs.rids_json) }}
runs-on: ubuntu-22.04
steps:
- name: Get Ancillaries
id: ancillaries
uses: actions/download-artifact@v3
with:
name: Ancillaries-${{ matrix.version }}
- name: Data
id: data
env:
debug: ${{ needs.check.outputs.debug }}
version: ${{ matrix.version }}
gitUrl: ${{ needs.check.outputs.gitUrl }}
releasePrefix: ${{ needs.check.outputs.releasePrefix }}
rid: ${{ matrix.rid }}
manifest: ${{steps.ancillaries.outputs.download-path}}/manifest.json
this_repo_url: ${{ github.repositoryUrl }}
this_repo_commit: ${{ github.sha }}
this_repo_branch: ${{ github.ref_name }}
run: |
if [[ ! -s "$manifest" ]] ; then
echo "Manifest does not exist yet at $manifest"
ls -la
unzip ./*.zip
ls -la
[[ ! -s "$manifest" ]] && exit 1
echo "Manifest now exists at $manifest"
fi
if ! ridJson="$( jq -c ".platforms[] | select(.rid==\"${rid}\")" "$manifest" )" ; then
echo -e "Problem getting JSON for $rid from $manifest:\n$ridJson"
#exit 1
fi
if [[ "$ridJson" == "" ]] ; then
echo "No manifest for $rid, so no need to continue."
continue="false"
else
echo -n "Reading details; "
if gitCommit="$( jq -r ".gitCommit" "$manifest" )" ; then
echo -n "git commit ${gitCommit}, "
else
echo "Problem getting gitCommit from manifest: $gitCommit"
fi
if gitBranch="$( jq -r ".gitBranch" "$manifest" )" ; then
echo -n "git branch ${gitBranch}, "
else
echo "Problem getting gitBranch from manifest: $gitBranch"
fi
if location="$( jq -r ".location" <<< "$ridJson" )" ; then
echo -n "location ${location}, "
else
echo "Problem getting location from manifest: $location"
fi
if filename="$( jq -r ".filename" <<< "$ridJson" )" ; then
echo -n "filename ${filename}, "
else
echo "Problem getting filename from manifest: $filename"
fi
echo "done."
continue="true"
fi
# If this is not a produciton build (so it will use our GitHub store), we have to lie about where it comes from
if [[ "$debug" == "true" ]] ; then
echo "Note: this is a workaround"
gitUrl="$this_repo_url"
gitCommit="$this_repo_commit"
gitBranch="$this_repo_branch"
fi
#shellcheck disable=SC2129
echo "filename=${filename}" >> "$GITHUB_OUTPUT"
echo "location=${location}" >> "$GITHUB_OUTPUT"
echo "packageName=StirlingLabs.MsQuic.Bindings.runtime.${rid}.openssl" >> "$GITHUB_OUTPUT"
echo "gitUrl=${gitUrl}" >> "$GITHUB_OUTPUT"
echo "gitCommit=${gitCommit}" >> "$GITHUB_OUTPUT"
echo "gitBranch=${gitBranch}" >> "$GITHUB_OUTPUT"
echo "continue=${continue}" >> "$GITHUB_OUTPUT"
- name: Get Libraries
if: steps.data.outputs.continue == 'true'
id: libraries
uses: actions/download-artifact@v3
with:
name: Libraries-${{ matrix.version }}
- name: Show File Context
if: steps.data.outputs.continue == 'true'
run: |
find .
- name: Create NuSpec
if: steps.data.outputs.continue == 'true'
id: nuspec
uses: StirlingLabs/CreateNuSpecAction@main
with:
id: ${{ steps.data.outputs.packageName }}
version: ${{ matrix.version }}
title: MsQuic runtime for ${{ matrix.rid }} ${{ needs.check.outputs.releasePrefix }}${{ matrix.version }}
description: |
Platform-specific runtime for MsQuic, Microsoft's C implementation of the IETF QUIC protocol.
fileSources: ${{ steps.libraries.outputs.download-path }}/${{ steps.data.outputs.location }}
fileTargets: runtimes/${{ matrix.rid }}/native/${{ steps.data.outputs.filename }}
readme: ${{ steps.ancillaries.outputs.download-path }}/${{ needs.binaries.outputs.readme }}
icon: ${{ steps.ancillaries.outputs.download-path }}/${{ needs.binaries.outputs.icon }}
gitUrl: ${{ steps.data.outputs.gitUrl }}
gitBranch: ${{ steps.data.outputs.gitBranch }}
gitCommit: ${{ steps.data.outputs.gitCommit }}
targetFrameworks: net6.0;netstandard2.0;netstandard2.1
- name: Build NuPkg
if: steps.data.outputs.continue == 'true'
id: build
env:
nuspec: ${{ steps.nuspec.outputs.filename }}
run: |
nuget pack $nuspec
[ $? -eq 0 ] && continue="true" || continue="false"
echo "continue=${continue}" >> $GITHUB_OUTPUT
ls -la
- name: Push NuPkg
if: steps.build.outputs.continue == 'true'
id: push
env:
debug: ${{ needs.check.outputs.debug }}
githubKey: ${{ github.token }}
githubUrl: "https://nuget.pkg.github.com/${{github.repository_owner}}/index.json"
nugetKey: ${{ secrets.NUGET_STIRLINGLABS_API_KEY }}
nugetUrl: "https://api.nuget.org/v3/index.json"
run: |
if [[ "$debug" == "true" ]] ; then
key="$githubKey" && url="$githubUrl"
else
key="$nugetKey" && url="$nugetUrl"
fi
if dotnet nuget push ./*.nupkg -k "$key" -s "$url" --no-symbols --skip-duplicate ; then
continue="true"
else
continue="false"
echo "Failed to push NuPkg to $url"
fi
echo "continue=${continue}" >> "$GITHUB_OUTPUT"
- name: Summary
if: steps.push.outputs.continue == 'true'
id: summary
env:
id: ${{ steps.data.outputs.packageName }}
version: ${{ matrix.version }}
rid: ${{ matrix.rid }}
run: |
echo "### Uploaded NuPkg for [${id}](https://www.nuget.org/packages/${id}) ${version} ${rid}." >> "$GITHUB_STEP_SUMMARY"
code:
name: Get Upstream Code
needs: [ check ]
if: needs.check.outputs.continue == 'true'
runs-on: ubuntu-22.04
steps:
- name: Get Our Source
uses: actions/checkout@v3
with:
submodules: true
- name: Get Latest Code Archive
id: retrieve
env:
upstream: ${{ needs.check.outputs.upstream }}
import: 'src/cs/lib'
target: 'StirlingLabs.MsQuic.Bindings'
run: |
base="${upstream}"
echo "base is ${base}"
if ! latestJson="$(curl -s https://github.com/repos/${upstream}/releases/latest)" ; then
echo "Failed to get latest release for ${upstream}: $latestJson"
exit 1
fi
if ! version="$(jq -r ".tag_name" <<< "$latestJson")" ; then
echo -e "Failed to get version from JSON: $version\nsource:\n$latestJson"
exit 1
fi
if ! url="$(jq -r ".zipball_url" <<< "$latestJson")" ; then
echo -e "Failed to get URL from JSON: $url\nsource:\n$latestJson"
exit 1
fi
if ! wget --quiet "${url}" -O upstream.zip ; then
echo "Failed to download ${url}"
exit 1
fi
mkdir -p "${base}"
unzip upstream.zip -d "${base}"
rm -f upstream.zip
subdir="$(ls "${base}")" && subdirArray=( $subdir )
if [[ "${#subdirArray[@]}" != "1" ]] ; then
echo "${#subdirArray[@]} objects in $base ... $subdir"
exit 1
fi
codebase="${base}/${subdir}"
echo "base=${base}" >> "$GITHUB_OUTPUT"
echo "source=${codebase}/${import}" >> "$GITHUB_OUTPUT"
echo "target=${target}" >> "$GITHUB_OUTPUT"
echo "version=${version}" >> "$GITHUB_OUTPUT"
- name: Edit Upstream Files
id: edit
env:
base: ${{ steps.retrieve.outputs.base }}
source: ${{ steps.retrieve.outputs.source }}
target: ${{ steps.retrieve.outputs.target }}/Imported
run: |
ls -la "${source}"
files="${source}/*.cs"
for file in $files ; do
echo -n "Processing $file ... "
if [[ "$file" != *"InternalsVisible.cs" ]] ; then
sed -i '1i \#nullable enable' "$file" && echo -n "nullable " || echo -n "‼️ nullable failed ‼️ "
sed -i 's/\(^\s*\) \(\binternal\b\)/\1 public/' "$file" && echo -n "public " || echo -n "‼️ public failed ‼️ "
sed -i 's/\bMicrosoft\.Quic\b/StirlingLabs.MsQuic.Bindings/' "$file" && echo -n "namespace " || echo -n "‼️ namespace failed ‼️ "
sed -i 's/\(^.*DllImport.\{1,3\}\"msquic\)\(\"\)/\1-openssl\2/' "$file" && echo -n "openssl " || echo -n "‼️ openssl failed ‼️ "
echo "done."
mv -f "$file" "${target}/"
fi
done
rm -Rf "$base"
ls -la "$target"
- name: Update Our Files
id: update
env:
target: ${{ steps.retrieve.outputs.target }}
version: ${{ steps.retrieve.outputs.version }}
releasePrefix: ${{ needs.check.outputs.releasePrefix }}
run: |
rawVersion="${version#"$releasePrefix"}"
echo "Updating files for version $version ($rawVersion)"
if [[ "$rawVersion" == "" ]] ; then
echo "Version not set, can't continue."
exit 1
fi
# file="${target}/${target}.csproj"
# [[ -f "$file" ]] && echo -n "Editing $file ... " || echo -n "Can't find $file ... "
# sed -i "s/\(\bStirlingLabs\.MsQuic\.Bindings\.runtime\.\(linux\|osx\|win\).*\.openssl.*Version=\"\)\(.*\)\(\"\)/\1${rawVersion}\4/" "$file" && echo "done." || echo "failed‼️"
file="MsQuicBindingsVersionOnly.proj"
[[ -f "$file" ]] && echo -n "Replacing $file ... " || echo -n "Creating $file ... "
echo "<Project><PropertyGroup><StirlingLabsMsQuicRuntimeVersion>${version:1}</StirlingLabsMsQuicRuntimeVersion></PropertyGroup></Project>" > "$file" && echo "done." || echo "failed‼️"
cat "$file"
- name: Create PR
uses: peter-evans/create-pull-request@v5
with:
commit-message: Update to incorporate upstream changes in ${{ steps.retrieve.outputs.version }}
base: main
branch: upstream-${{ steps.retrieve.outputs.version }}
delete-branch: true
title: Update to ${{ steps.check.outputs.upstream }} ${{ steps.retrieve.outputs.version }}
body: |
Automatically prepared the following changes:
- Re-imported upstream files and re-applied our modifications
- Updated projects to refer to new upstream libraries
- name: Summary
id: summary
env:
version: ${{ steps.retrieve.outputs.version }}
run: |
echo "### Created PR for update to ${version}." >> "$GITHUB_STEP_SUMMARY"