diff --git a/.github/workflows/assert-contents.sh b/.github/workflows/assert-contents.sh new file mode 100644 index 0000000..ebefdfb --- /dev/null +++ b/.github/workflows/assert-contents.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +echo "Unzipping version from NuGet" +ls from-nuget.nupkg +mkdir from-nuget && cp from-nuget.nupkg from-nuget/zip.zip && cd from-nuget && unzip zip.zip && rm zip.zip && cd - || exit 1 + +echo "Unzipping version from local build" +ls packed/ +mkdir from-local && cp packed/*.nupkg from-local/zip.zip && cd from-local && unzip zip.zip && rm zip.zip && cd - || exit 1 + +cd from-local && find . -type f -exec sha256sum {} \; | sort > ../from-local.txt && cd .. || exit 1 +cd from-nuget && find . -type f -and -not -name '.signature.p7s' -exec sha256sum {} \; | sort > ../from-nuget.txt && cd .. || exit 1 + +diff from-local.txt from-nuget.txt diff --git a/.github/workflows/dotnet.yaml b/.github/workflows/dotnet.yaml index d454a97..edc4ae2 100644 --- a/.github/workflows/dotnet.yaml +++ b/.github/workflows/dotnet.yaml @@ -182,11 +182,34 @@ jobs: steps: - run: echo "All required checks complete." + attestation: + runs-on: ubuntu-latest + needs: [all-required-checks-complete] + if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }} + permissions: + id-token: write + attestations: write + contents: read + steps: + - name: Download NuGet artifact + uses: actions/download-artifact@v4 + with: + name: nuget-package + path: packed + - name: Attest Build Provenance + uses: actions/attest-build-provenance@897ed5eab6ed058a474202017ada7f40bfa52940 # v1.0.0 + with: + subject-path: "packed/WoofWare.PrattParser.*.nupkg" + nuget-publish: runs-on: ubuntu-latest if: ${{ !github.event.repository.fork && github.ref == 'refs/heads/main' }} needs: [all-required-checks-complete] environment: main-deploy + permissions: + id-token: write + attestations: write + contents: read steps: - uses: actions/checkout@v4 - name: Install Nix @@ -200,7 +223,25 @@ jobs: name: nuget-package path: packed - name: Publish to NuGet - run: nix develop --command dotnet nuget push "packed/WoofWare.PrattParser.*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json --skip-duplicate + id: publish-success + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + run: 'nix develop --command bash ./.github/workflows/nuget-push.sh "packed/WoofWare.PrattParser.*.nupkg"' + - name: Wait for availability + if: steps.publish-success.outputs.result == 'published' + env: + PACKAGE_VERSION: ${{ steps.publish-success.outputs.version }} + run: 'echo "$PACKAGE_VERSION" && while ! curl -L --fail -o from-nuget.nupkg "https://www.nuget.org/api/v2/package/WoofWare.PrattParser/$PACKAGE_VERSION" ; do sleep 10; done' + # Astonishingly, NuGet.org considers it to be "more secure" to tamper with my package after upload (https://devblogs.microsoft.com/nuget/introducing-repository-signatures/). + # So we have to *re-attest* it after it's uploaded. Mind-blowing. + - name: Assert package contents + if: steps.publish-success.outputs.result == 'published' + run: 'bash ./.github/workflows/assert-contents.sh' + - name: Attest Build Provenance + if: steps.publish-success.outputs.result == 'published' + uses: actions/attest-build-provenance@897ed5eab6ed058a474202017ada7f40bfa52940 # v1.0.0 + with: + subject-path: "from-nuget.nupkg" github-release: runs-on: ubuntu-latest diff --git a/.github/workflows/nuget-push.sh b/.github/workflows/nuget-push.sh new file mode 100644 index 0000000..edc170d --- /dev/null +++ b/.github/workflows/nuget-push.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +SOURCE_NUPKG=$(find . -type f -name '*.nupkg') + +PACKAGE_VERSION=$(basename "$SOURCE_NUPKG" | rev | cut -d '.' -f 2-4 | rev) + +echo "version=$PACKAGE_VERSION" >> "$GITHUB_OUTPUT" + +tmp=$(mktemp) + +if ! dotnet nuget push "$SOURCE_NUPKG" --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json > "$tmp" ; then + cat "$tmp" + if grep 'already exists and cannot be modified' "$tmp" ; then + echo "result=skipped" >> "$GITHUB_OUTPUT" + exit 0 + else + echo "Unexpected failure to upload" + exit 1 + fi +fi + +cat "$tmp" + +echo "result=published" >> "$GITHUB_OUTPUT" diff --git a/PrattParser.Example/Example.fs b/PrattParser.Example/Example.fs index a63297b..3da931d 100644 --- a/PrattParser.Example/Example.fs +++ b/PrattParser.Example/Example.fs @@ -2,7 +2,7 @@ namespace ParseExample open System open System.Globalization -open PrattParser +open WoofWare.PrattParser [] module Example = diff --git a/PrattParser.Test/TestLexer.fs b/PrattParser.Test/TestLexer.fs index 52678c7..635c439 100644 --- a/PrattParser.Test/TestLexer.fs +++ b/PrattParser.Test/TestLexer.fs @@ -1,4 +1,4 @@ -namespace PrattParser.Test +namespace WoofWare.PrattParser.Test open ParseExample open NUnit.Framework diff --git a/PrattParser.Test/TestParser.fs b/PrattParser.Test/TestParser.fs index 4d481fd..aca3614 100644 --- a/PrattParser.Test/TestParser.fs +++ b/PrattParser.Test/TestParser.fs @@ -1,7 +1,7 @@ -namespace PrattParser.Test +namespace WoofWare.PrattParser.Test open ParseExample -open PrattParser +open WoofWare.PrattParser open NUnit.Framework open FsUnitTyped diff --git a/PrattParser.Test/TestSurface.fs b/PrattParser.Test/TestSurface.fs index 5a8238b..a325521 100644 --- a/PrattParser.Test/TestSurface.fs +++ b/PrattParser.Test/TestSurface.fs @@ -1,7 +1,7 @@ -namespace PrattParser.Test +namespace WoofWare.PrattParser.Test open NUnit.Framework -open PrattParser +open WoofWare.PrattParser open ApiSurface [] diff --git a/PrattParser/Parser.fs b/PrattParser/Parser.fs index 424ca16..c4cfff5 100644 --- a/PrattParser/Parser.fs +++ b/PrattParser/Parser.fs @@ -1,4 +1,4 @@ -namespace PrattParser +namespace WoofWare.PrattParser /// Specification of how to parse things which act like brackets: that is, they start with a token, /// then consume some stuff, then there's another token to mark the end. diff --git a/PrattParser/SurfaceBaseline.txt b/PrattParser/SurfaceBaseline.txt index 08bf0cf..dea63b1 100644 --- a/PrattParser/SurfaceBaseline.txt +++ b/PrattParser/SurfaceBaseline.txt @@ -1,18 +1,18 @@ -PrattParser.BracketLikeParser`2 inherit obj -PrattParser.BracketLikeParser`2..ctor [constructor]: (bool, bool, 'tokenTag list, 'expr list -> 'expr) -PrattParser.BracketLikeParser`2.BoundaryTokens [property]: [read-only] 'tokenTag list -PrattParser.BracketLikeParser`2.Construct [property]: [read-only] 'expr list -> 'expr -PrattParser.BracketLikeParser`2.ConsumeAfterFinalToken [property]: [read-only] bool -PrattParser.BracketLikeParser`2.ConsumeBeforeInitialToken [property]: [read-only] bool -PrattParser.BracketLikeParser`2.get_BoundaryTokens [method]: unit -> 'tokenTag list -PrattParser.BracketLikeParser`2.get_Construct [method]: unit -> ('expr list -> 'expr) -PrattParser.BracketLikeParser`2.get_ConsumeAfterFinalToken [method]: unit -> bool -PrattParser.BracketLikeParser`2.get_ConsumeBeforeInitialToken [method]: unit -> bool -PrattParser.Parser inherit obj -PrattParser.Parser.execute [static method]: PrattParser.Parser<'tokenTag, 'token, 'expr> -> string -> 'token list -> ('expr * 'token list) -PrattParser.Parser.make [static method]: ('token -> 'tokenTag) -> (string -> 'token -> 'expr option) -> PrattParser.Parser<'tokenTag, 'token, 'expr> -PrattParser.Parser.withBracketLike [static method]: 'tokenTag -> PrattParser.BracketLikeParser<'tokenTag, 'expr> -> PrattParser.Parser<'tokenTag, 'token, 'expr> -> PrattParser.Parser<'tokenTag, 'token, 'expr> -PrattParser.Parser.withInfix [static method]: 'tokenTag -> (int, int) -> ('expr -> 'expr -> 'expr) -> PrattParser.Parser<'tokenTag, 'token, 'expr> -> PrattParser.Parser<'tokenTag, 'token, 'expr> -PrattParser.Parser.withUnaryPostfix [static method]: 'tokenTag -> (int, unit) -> ('expr -> 'expr) -> PrattParser.Parser<'tokenTag, 'token, 'expr> -> PrattParser.Parser<'tokenTag, 'token, 'expr> -PrattParser.Parser.withUnaryPrefix [static method]: 'tokenTag -> (unit, int) -> ('expr -> 'expr) -> PrattParser.Parser<'tokenTag, 'token, 'expr> -> PrattParser.Parser<'tokenTag, 'token, 'expr> -PrattParser.Parser`3 inherit obj \ No newline at end of file +WoofWare.PrattParser.BracketLikeParser`2 inherit obj +WoofWare.PrattParser.BracketLikeParser`2..ctor [constructor]: (bool, bool, 'tokenTag list, 'expr list -> 'expr) +WoofWare.PrattParser.BracketLikeParser`2.BoundaryTokens [property]: [read-only] 'tokenTag list +WoofWare.PrattParser.BracketLikeParser`2.Construct [property]: [read-only] 'expr list -> 'expr +WoofWare.PrattParser.BracketLikeParser`2.ConsumeAfterFinalToken [property]: [read-only] bool +WoofWare.PrattParser.BracketLikeParser`2.ConsumeBeforeInitialToken [property]: [read-only] bool +WoofWare.PrattParser.BracketLikeParser`2.get_BoundaryTokens [method]: unit -> 'tokenTag list +WoofWare.PrattParser.BracketLikeParser`2.get_Construct [method]: unit -> ('expr list -> 'expr) +WoofWare.PrattParser.BracketLikeParser`2.get_ConsumeAfterFinalToken [method]: unit -> bool +WoofWare.PrattParser.BracketLikeParser`2.get_ConsumeBeforeInitialToken [method]: unit -> bool +WoofWare.PrattParser.Parser inherit obj +WoofWare.PrattParser.Parser.execute [static method]: WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> -> string -> 'token list -> ('expr * 'token list) +WoofWare.PrattParser.Parser.make [static method]: ('token -> 'tokenTag) -> (string -> 'token -> 'expr option) -> WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> +WoofWare.PrattParser.Parser.withBracketLike [static method]: 'tokenTag -> WoofWare.PrattParser.BracketLikeParser<'tokenTag, 'expr> -> WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> -> WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> +WoofWare.PrattParser.Parser.withInfix [static method]: 'tokenTag -> (int, int) -> ('expr -> 'expr -> 'expr) -> WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> -> WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> +WoofWare.PrattParser.Parser.withUnaryPostfix [static method]: 'tokenTag -> (int, unit) -> ('expr -> 'expr) -> WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> -> WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> +WoofWare.PrattParser.Parser.withUnaryPrefix [static method]: 'tokenTag -> (unit, int) -> ('expr -> 'expr) -> WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> -> WoofWare.PrattParser.Parser<'tokenTag, 'token, 'expr> +WoofWare.PrattParser.Parser`3 inherit obj \ No newline at end of file diff --git a/PrattParser/version.json b/PrattParser/version.json index e0b6712..a216e9c 100644 --- a/PrattParser/version.json +++ b/PrattParser/version.json @@ -1,5 +1,5 @@ { - "version": "0.1", + "version": "0.2", "publicReleaseRefSpec": [ "^refs/heads/main$" ],