diff --git a/.cursor/Dockerfile b/.cursor/Dockerfile new file mode 100644 index 0000000..16944f9 --- /dev/null +++ b/.cursor/Dockerfile @@ -0,0 +1,17 @@ +# Cursor Cloud Agent image: .NET 10 SDK, Docker, and pre-restored NuGet packages for eShop.Web.slnf. +FROM mcr.microsoft.com/dotnet/sdk:10.0 + +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + docker.io \ + fuse-overlayfs \ + iptables \ + && rm -rf /var/lib/apt/lists/* \ + && mkdir -p /etc/docker \ + && printf '%s\n' '{' ' "storage-driver": "fuse-overlayfs"' '}' > /etc/docker/daemon.json + +WORKDIR /workspace + +# Restore during image build (NuGet is available on Cursor image build infrastructure). +COPY . . +RUN dotnet restore eShop.Web.slnf && dotnet build eShop.Web.slnf --no-restore diff --git a/.cursor/environment.json b/.cursor/environment.json new file mode 100644 index 0000000..85f5d66 --- /dev/null +++ b/.cursor/environment.json @@ -0,0 +1,6 @@ +{ + "build": { + "dockerfile": "Dockerfile", + "context": ".." + } +} diff --git a/.github/workflows/nuget-cache-artifact.yml b/.github/workflows/nuget-cache-artifact.yml new file mode 100644 index 0000000..1594cb3 --- /dev/null +++ b/.github/workflows/nuget-cache-artifact.yml @@ -0,0 +1,45 @@ +# Publishes a NuGet package cache tarball for Cloud Agent VMs where api.nuget.org is unreachable. +# Triggered only on this branch; safe to delete after cache is seeded in the VM image. +name: Publish NuGet cache artifact + +permissions: + contents: write + +on: + push: + branches: + - cursor/env-setup-nuget-cache-7ab0 + workflow_dispatch: + +jobs: + publish-nuget-cache: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup .NET + uses: actions/setup-dotnet@v3 + + - name: Restore solution + run: dotnet restore eShop.Web.slnf + + - name: Pack NuGet cache + run: tar -czf nuget-packages.tar.gz -C "$HOME/.nuget" packages + + - name: Upload artifact (Actions storage) + uses: actions/upload-artifact@v4 + with: + name: nuget-packages + path: nuget-packages.tar.gz + retention-days: 14 + + # GitHub Releases use github.com CDN (reachable when Azure blob storage is blocked). + - name: Upload to GitHub Release + env: + GH_TOKEN: ${{ github.token }} + run: | + TAG="nuget-cache-${{ github.run_id }}" + gh release create "$TAG" nuget-packages.tar.gz \ + --repo "${{ github.repository }}" \ + --title "NuGet cache (cloud agent)" \ + --notes "Temporary package cache for eShop.Web.slnf restore on networks without api.nuget.org access." diff --git a/AGENTS.md b/AGENTS.md index 3bbeb25..8f00c0b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -32,3 +32,40 @@ Microsoft [.NET eShop](https://github.com/dotnet/eShop) reference application. T - **Shared:** `eShop.ServiceDefaults` — OpenTelemetry, health checks, service discovery, HTTP resilience. Upstream: `https://github.com/dotnet/eShop`. Sync with `git fetch upstream && git merge upstream/main` (remote `upstream`). + +## Cursor Cloud specific instructions + +### Prerequisites on the VM + +- **Docker** must be running before AppHost (`dockerd` with `fuse-overlayfs` storage driver is typical in nested VMs). If `docker ps` fails with permission errors, ensure `/var/run/docker.sock` is writable or start `dockerd` manually. +- **.NET SDK 10** (see `global.json`; Ubuntu package `dotnet-sdk-10.0` is sufficient). +- **Node.js** for Playwright E2E (`npm ci` at repo root). + +### NuGet and LibMan on restricted networks + +Some Cloud Agent networks block TLS to `api.nuget.org` and Azure blob hosts. If `dotnet restore` fails with `NU1301` / `NU1900`: + +1. Seed the global package cache from the latest **`nuget-cache-*` GitHub Release** on this fork (asset `nuget-packages.tar.gz`), then restore with audit disabled: + ```bash + gh release download "$(gh release list -L 1 --json tagName -q '.[0].tagName')" -p nuget-packages.tar.gz -O /tmp/nuget-packages.tar.gz + mkdir -p ~/.nuget && tar -xzf /tmp/nuget-packages.tar.gz -C ~/.nuget + dotnet restore eShop.Web.slnf -p:NuGetAudit=false + ``` +2. Build with LibMan restore skipped when `cdnjs` is unreachable (vendor files under `src/Identity.API/wwwroot/lib/` or install via `npm pack`): + ```bash + dotnet build eShop.Web.slnf --no-restore -p:NuGetAudit=false -p:LibraryRestore=false + ``` + +Long-term: `.cursor/Dockerfile` pre-restores during the Cursor environment image build. + +### Run and verify + +| Goal | Command | +|------|---------| +| Build demo slice | `dotnet restore eShop.Web.slnf -p:NuGetAudit=false && dotnet build eShop.Web.slnf --no-restore -p:NuGetAudit=false -p:LibraryRestore=false` | +| Full stack | `export ESHOP_USE_HTTP_ENDPOINTS=1` then `dotnet run --project src/eShop.AppHost/eShop.AppHost.csproj` (omit `--no-build` after a clean build) | +| Web UI | `http://localhost:5045` (HTTP profile; see `ESHOP_USE_HTTP_ENDPOINTS` in `src/eShop.AppHost/Program.cs`) | +| Unit tests | `dotnet test --solution eShop.Web.slnf --no-build --filter "FullyQualifiedName~Ordering.UnitTests"` | +| E2E (AppHost already running) | `export USERNAME1=bob PASSWORD='Pass123$'` then `npx playwright test e2e/BrowseItemTest.spec.ts --project="e2e tests without logged in"` | + +Aspire dashboard URL is printed when AppHost starts (often `https://localhost:19888`).