diff --git a/.github/workflows/Build-Test-And-Deploy.yml b/.github/workflows/Build-Test-And-Deploy.yml index a2d75099..cd27eeea 100644 --- a/.github/workflows/Build-Test-And-Deploy.yml +++ b/.github/workflows/Build-Test-And-Deploy.yml @@ -80,6 +80,14 @@ jobs: cache-dir: buildkit-cache skip-extraction: false + - name: Generate Docker NuGet credentials config + env: + NUGET_FEED_TOKEN: ${{ secrets.AZURE_DEVOPS_PAT }} + run: | + mkdir -p "${RUNNER_TEMP}/nuget" + bash scripts/nuget/emit-creds-config.sh > "${RUNNER_TEMP}/nuget/NuGet.Config" + chmod 600 "${RUNNER_TEMP}/nuget/NuGet.Config" + # Only build for dev registry — prod gets the image via az acr import in deploy-production - name: Build Container Image if: github.event_name != 'pull_request_target' && github.event_name != 'pull_request' @@ -88,12 +96,16 @@ jobs: tags: ${{ vars.DEVCONTAINER_REGISTRY }}/essentialcsharpweb:${{ github.sha }},${{ vars.DEVCONTAINER_REGISTRY }}/essentialcsharpweb:latest file: ./EssentialCSharp.Web/Dockerfile context: . - secrets: | - "nuget_pat=${{ secrets.AZURE_DEVOPS_PAT }}" + secret-files: | + "nuget_config=${{ runner.temp }}/nuget/NuGet.Config" outputs: type=docker,dest=${{ github.workspace }}/essentialcsharpwebimage.tar cache-from: type=gha,scope=essentialcsharpweb-main cache-to: type=gha,mode=max,scope=essentialcsharpweb-main + - name: Remove Docker NuGet credentials config + if: always() + run: rm -f "${RUNNER_TEMP}/nuget/NuGet.Config" + - name: Upload artifact uses: actions/upload-artifact@v7 with: @@ -321,4 +333,3 @@ jobs: az logout az cache purge az account clear - diff --git a/EssentialCSharp.Web/Dockerfile b/EssentialCSharp.Web/Dockerfile index 682dd378..5c2c90d1 100644 --- a/EssentialCSharp.Web/Dockerfile +++ b/EssentialCSharp.Web/Dockerfile @@ -26,18 +26,13 @@ COPY EssentialCSharp.Chat.Tests/EssentialCSharp.Chat.Tests.csproj ./EssentialCSh COPY EssentialCSharp.Chat/EssentialCSharp.Chat.csproj ./EssentialCSharp.Chat/ COPY EssentialCSharp.Web.Tests/EssentialCSharp.Web.Tests.csproj ./EssentialCSharp.Web.Tests/ COPY EssentialCSharp.Web/EssentialCSharp.Web.csproj ./EssentialCSharp.Web/ -RUN --mount=type=secret,id=nuget_pat,required=false \ +RUN mkdir -p /root/.nuget/NuGet +RUN --mount=type=secret,id=nuget_config,required=false,target=/root/.nuget/NuGet/NuGet.Config \ --mount=type=cache,id=essentialcsharp-web-nuget,target=/root/.nuget/packages \ - if [ "$ACCESS_TO_NUGET_FEED" = "true" ] && [ ! -s /run/secrets/nuget_pat ]; then \ - echo "ERROR: ACCESS_TO_NUGET_FEED=true but nuget_pat secret is missing or empty" >&2; exit 1; \ + if [ "$ACCESS_TO_NUGET_FEED" = "true" ] && [ ! -s /root/.nuget/NuGet/NuGet.Config ]; then \ + echo "ERROR: ACCESS_TO_NUGET_FEED=true but nuget_config secret is missing or empty" >&2; exit 1; \ fi && \ - if [ "$ACCESS_TO_NUGET_FEED" = "true" ]; then \ - mkdir -p /root/.nuget/NuGet && \ - printf '\n\n \n \n \n \n \n \n\n' \ - "$(cat /run/secrets/nuget_pat)" > /root/.nuget/NuGet/NuGet.Config; \ - fi && \ - dotnet restore "EssentialCSharp.Web.slnx" -p:AccessToNugetFeed=$ACCESS_TO_NUGET_FEED && \ - rm -f /root/.nuget/NuGet/NuGet.Config + dotnet restore "EssentialCSharp.Web.slnx" -p:AccessToNugetFeed=$ACCESS_TO_NUGET_FEED COPY . . COPY --from=frontend-build /frontend/EssentialCSharp.Web/wwwroot/dist ./EssentialCSharp.Web/wwwroot/dist RUN --mount=type=cache,id=essentialcsharp-web-nuget,target=/root/.nuget/packages \ diff --git a/scripts/nuget/emit-creds-config.sh b/scripts/nuget/emit-creds-config.sh new file mode 100644 index 00000000..ab5f58a9 --- /dev/null +++ b/scripts/nuget/emit-creds-config.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +set -euo pipefail + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=scripts/nuget/feed.sh +source "${script_dir}/feed.sh" + +token="${1:-${NUGET_FEED_TOKEN:-}}" +username="${2:-${FEED_USERNAME}}" + +if [[ -z "${token}" ]]; then + echo "emit-creds-config.sh: no token (pass as \$1 or set NUGET_FEED_TOKEN)" >&2 + exit 1 +fi + +xml_escape() { + local value="${1}" + value="${value//&/&}" + value="${value///>}" + value="${value//\"/"}" + printf '%s' "${value}" +} + +if [[ ! "${FEED_NAME}" =~ ^[A-Za-z_][A-Za-z0-9._-]*$ ]]; then + echo "emit-creds-config.sh: FEED_NAME must be a valid NuGet.Config XML element name" >&2 + exit 1 +fi + +escaped_username="$(xml_escape "${username}")" +escaped_token="$(xml_escape "${token}")" + +cat < + + + <${FEED_NAME}> + + + + + +EOF diff --git a/scripts/nuget/feed.sh b/scripts/nuget/feed.sh new file mode 100644 index 00000000..12b8944c --- /dev/null +++ b/scripts/nuget/feed.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +FEED_NAME="${FEED_NAME:-EssentialCSharp}" +FEED_USERNAME="${FEED_USERNAME:-az}"