From c0fe3c0bcd50ef996f8b5506d9d54f74dd1ae1d7 Mon Sep 17 00:00:00 2001 From: ahall Date: Sat, 11 Jul 2026 12:10:44 +0100 Subject: [PATCH 1/2] ci: validate docs on PR and only deploy Pages on release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - build-docs.yml: add a pull_request trigger (and keep push to main, for parity) that runs a new 'validate' job — a strict mkdocs build to catch broken internal links/anchors/nav entries, plus lychee to catch dead external links. Never deploys. - Gate the 'deploy' job to release: published (or a manual dispatch against a release tag), matching the build-library.yml/build-template.yml convention, instead of deploying on every push to main. - Move the Pages-specific permissions/concurrency group and the configure-pages step to the 'deploy' job only, so PR/push validation runs are unaffected and don't need pages:write. - Fix the broken links/anchors surfaced by the new checks: a stale self-referential anchor link, two dead GitHub file/profile links, a removed test-only MySQL doc link, a moved Azure Cosmos DB for MongoDB doc URL, an old Auth0 quickstart URL, and a URL missing a '/'. Closes #562 --- .github/workflows/build-docs.yml | 77 ++++++++++++++++++----- docs/in-depth/client/advanced/maui-aot.md | 2 +- docs/in-depth/server/db/cosmos-sdk.md | 2 +- docs/in-depth/server/db/cosmos.md | 2 +- docs/in-depth/server/db/mongodb.md | 4 +- docs/in-depth/server/db/mysql.md | 1 - docs/tutorial/client/part-1.md | 2 +- docs/tutorial/client/part-2.md | 2 +- docs/tutorial/server/part-4.md | 2 +- 9 files changed, 70 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index fc78cbe4..f0d16246 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -1,26 +1,28 @@ -name: Deploy documentation site to GitHub Pages +name: Build and Deploy Documentation Site on: push: branches: [ main ] - paths: [ 'docs/**', 'mkdocs.yml', 'mkdocs.shared.yml', 'mkdocs.production.yml' ] + paths: [ 'docs/**', 'mkdocs.yml', 'mkdocs.shared.yml', 'mkdocs.production.yml', '.github/workflows/build-docs.yml' ] + pull_request: + branches: [ main ] + paths: [ 'docs/**', 'mkdocs.yml', 'mkdocs.shared.yml', 'mkdocs.production.yml', '.github/workflows/build-docs.yml' ] + release: + types: [ published ] workflow_dispatch: permissions: contents: read - pages: write - id-token: write - -concurrency: - group: "pages" - cancel-in-progress: false defaults: run: shell: bash jobs: + # Builds the production site and uploads it as a Pages artifact. Only needs to run when the + # artifact might actually be deployed (see the 'deploy' job below). build: + if: ${{ github.event_name == 'release' || github.event_name == 'workflow_dispatch' }} runs-on: ubuntu-latest steps: - name: Checkout Repository @@ -36,26 +38,71 @@ jobs: - name: Install mkdocs run: pip install mkdocs mkdocs-mermaid2-plugin - - name: Setup Pages - id: pages - uses: actions/configure-pages@v6 - - name: Generate site - run : mkdocs build -f ./mkdocs.production.yml + run: mkdocs build -f ./mkdocs.production.yml - name: Upload artifact uses: actions/upload-pages-artifact@v5 with: path: ./site - # Deployment job + # Validates the docs site without ever deploying it: a strict mkdocs build catches broken + # internal links/anchors/nav entries, and lychee catches dead external links. Runs on every PR + # (and push to main, for parity) so problems are caught before they reach a release. --strict is + # deliberately only used here (not baked into mkdocs.production.yml or used by the 'build' job + # above) so that a stray warning can never block the artifact that 'deploy' publishes. + validate: + if: ${{ github.event_name == 'pull_request' || github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Install Python + uses: actions/setup-python@v6 + with: + python-version: 3.x + + - name: Install mkdocs + run: pip install mkdocs mkdocs-mermaid2-plugin + + - name: Validate site (strict build) + run: mkdocs build --strict -f ./mkdocs.production.yml + + - name: Check for broken links + uses: lycheeverse/lychee-action@v2 + with: + args: >- + --no-progress + --scheme https --scheme http + --user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" + --exclude "^https://dev\.mysql\.com/" + --exclude "^https://developers\.facebook\.com/" + 'docs/**/*.md' + token: ${{ secrets.GITHUB_TOKEN }} + fail: true + + # Only deploys to GitHub Pages on a published release (or a manual dispatch against a release + # tag), never on every push to main and never on a plain feature-branch dispatch. deploy: + if: >- + ${{ github.event_name == 'release' || + (github.event_name == 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/')) }} + needs: build + permissions: + pages: write + id-token: write + concurrency: + group: "pages" + cancel-in-progress: false environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest - needs: build steps: + - name: Setup Pages + uses: actions/configure-pages@v6 + - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v5 diff --git a/docs/in-depth/client/advanced/maui-aot.md b/docs/in-depth/client/advanced/maui-aot.md index 07ae2e7a..566be10b 100644 --- a/docs/in-depth/client/advanced/maui-aot.md +++ b/docs/in-depth/client/advanced/maui-aot.md @@ -9,7 +9,7 @@ When using [Native AOT with .NET MAUI](https://learn.microsoft.com/dotnet/maui/d The following are basic instructions on how to fulfill these requirements. However, you should consult the official documentation (linked above) for each requirement. !!! info - Thanks to [Richard Perry](https://github.com/richard-einfinity) for providing the detailed instructions for enabling Native AOT support. + Thanks to Richard Perry for providing the detailed instructions for enabling Native AOT support. ## Compiled models diff --git a/docs/in-depth/server/db/cosmos-sdk.md b/docs/in-depth/server/db/cosmos-sdk.md index 1d28f8e2..d563adbf 100644 --- a/docs/in-depth/server/db/cosmos-sdk.md +++ b/docs/in-depth/server/db/cosmos-sdk.md @@ -12,7 +12,7 @@ Use the [CommunityToolkit.Datasync.Server.CosmosDb](https://www.nuget.org/packag Azure Cosmos DB is a fully managed NoSQL database for high-performance applications of any size or scale. See [Azure Cosmos DB for NoSQL .NET SDK](https://learn.microsoft.com/azure/cosmos-db/nosql/quickstart-dotnet) for information on using Azure Cosmos DB via the SDK. !!! info - The Cosmos DB library and sample has been kindly contributed to the community by [@richard-einfinity](https://github.com/richard-einfinity). + The Cosmos DB library and sample has been kindly contributed to the community by @richard-einfinity. ## Set up diff --git a/docs/in-depth/server/db/cosmos.md b/docs/in-depth/server/db/cosmos.md index 4df1af54..8968d027 100644 --- a/docs/in-depth/server/db/cosmos.md +++ b/docs/in-depth/server/db/cosmos.md @@ -43,7 +43,7 @@ Azure Cosmos DB is a fully managed NoSQL database for high-performance applicati You must include a composite index for each combination of filters that you require. A "client-side evaluation" exception will be generated (which is turned into a `400 Bad Request` by the server) if you do not have the appropriate composite indices for the request. - You can also review our [bicep module](https://github.com/CommunityToolkit/Datasync/blob/main/tests/infra/databases/cosmos.bicep) that we use for testing. + You can also review the [bicep module](https://github.com/CommunityToolkit/Datasync/blob/main/samples/datasync-server-cosmosdb-singlecontainer/infra/resources.bicep) used by our Cosmos DB sample. If you pull a subset of items in the table, ensure you specify all properties involved in the query. diff --git a/docs/in-depth/server/db/mongodb.md b/docs/in-depth/server/db/mongodb.md index bbcbaddc..89864b39 100644 --- a/docs/in-depth/server/db/mongodb.md +++ b/docs/in-depth/server/db/mongodb.md @@ -32,9 +32,9 @@ In your table controller: ## Known issues -The MongoDB implementation within Cosmos is split into vCore and RU format (also known as dedicated and serverless SKUs). Do not use the "serverless" or RU SKU. Ensure you are using Azure Cosmos DB for MongoDB (vCore). For more information, see [the Azure documentation](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/). +The MongoDB implementation within Cosmos is split into vCore and RU format (also known as dedicated and serverless SKUs). Do not use the "serverless" or RU SKU. Ensure you are using Azure Cosmos DB for MongoDB (vCore). For more information, see [the Azure documentation](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/overview). ## Support and further information * [MongoDb C# Driver (v3.1)](https://www.mongodb.com/docs/drivers/csharp/current/?msockid=3814d66fce6360e01644c3edcf2061bc) -* [Azure Cosmos DB for MongoDB (vCore)](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/) +* [Azure Cosmos DB for MongoDB (vCore)](https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/overview) diff --git a/docs/in-depth/server/db/mysql.md b/docs/in-depth/server/db/mysql.md index f67a65a2..e3a9e4fc 100644 --- a/docs/in-depth/server/db/mysql.md +++ b/docs/in-depth/server/db/mysql.md @@ -25,4 +25,3 @@ In the `OnModelCreating()` method of your context, add the following for each en * [Official docs: MySql and Entity Framework Core](https://dev.mysql.com/doc/connector-net/en/connector-net-entityframework-core.html) * [Pomelo docs: MySql](https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql) -* [Test MySQL Context](https://github.com/CommunityToolkit/Datasync/blob/main/tests/CommunityToolkit.Datasync.TestCommon/Databases/MySQL/MysqlDbContext.cs) diff --git a/docs/tutorial/client/part-1.md b/docs/tutorial/client/part-1.md index fef71d7a..dd7c3637 100644 --- a/docs/tutorial/client/part-1.md +++ b/docs/tutorial/client/part-1.md @@ -174,7 +174,7 @@ Each operation can take a `DatasyncServiceOptions` object with the following pro ## Querying for data -The final method in our sample implementation is the query interface. The `DatasyncServiceClient` class implements `TableQuery` - a subset of LINQ that is supported by our implementation of OData. When the query is transmitted to the remote service, it is turned into an OData query string. Full details are provided in the [in-depth documentation](https://communitytoolkit.github.io/Datasync/in-depth/client/online-operations/index.html#querying-for-data). To query for all data: +The final method in our sample implementation is the query interface. The `DatasyncServiceClient` class implements `TableQuery` - a subset of LINQ that is supported by our implementation of OData. When the query is transmitted to the remote service, it is turned into an OData query string. Full details are provided in the [in-depth documentation](../../in-depth/client/online.md#querying-for-data). To query for all data: public async Task> GetAllTodoItemsAsync(CancellationToken cancellationToken = default) => await client.ToListAsync(cancellationToken); diff --git a/docs/tutorial/client/part-2.md b/docs/tutorial/client/part-2.md index d007e88b..0d30c38e 100644 --- a/docs/tutorial/client/part-2.md +++ b/docs/tutorial/client/part-2.md @@ -285,7 +285,7 @@ In the [next tutorial](./part-3.md), we'll take a final look at the online clien [OIDC]: https://www.microsoft.com/security/business/security-101/what-is-openid-connect-oidc?msockid=3814d66fce6360e01644c3edcf2061bc [Google]: https://developers.google.com/identity/openid-connect/openid-connect [Facebook]: https://developers.facebook.com/docs/facebook-login -[Auth0]: https://auth0.com/docs/quickstart/backend/aspnet-core-webapi/01-authorization +[Auth0]: https://auth0.com/docs/quickstart/backend/aspnet-core-webapi [OpenID Dict]: https://openiddict.com/ [Duende Identity Server]: https://duendesoftware.com/products/identityserver [Microsoft Entra ID]: https://learn.microsoft.com/en-us/entra/fundamentals/whatis diff --git a/docs/tutorial/server/part-4.md b/docs/tutorial/server/part-4.md index 0b6f1910..6000f611 100644 --- a/docs/tutorial/server/part-4.md +++ b/docs/tutorial/server/part-4.md @@ -53,7 +53,7 @@ Now, I want to implement some business rules: This will demonstrate the first two methods that are needed for an access control provider. !!! tip Using the IHttpContextAccessor - Most access control providers need asynchronous access to the `HttpContext` of a request. This is handled using the `IHttpContextAccessor`. For details, see [the documentation](https://learn.microsoft.comaspnet/core/fundamentals/http-context). The documentation will tell you to add the following to your application services. + Most access control providers need asynchronous access to the `HttpContext` of a request. This is handled using the `IHttpContextAccessor`. For details, see [the documentation](https://learn.microsoft.com/aspnet/core/fundamentals/http-context). The documentation will tell you to add the following to your application services. ```csharp builder.Services.AddHttpContextAccessor(); From 7abe3d726cd08f9b8aabcd9ce2e1fb90e917b35f Mon Sep 17 00:00:00 2001 From: ahall Date: Sat, 11 Jul 2026 12:12:44 +0100 Subject: [PATCH 2/2] ci: exclude dotnet.microsoft.com from link check (bot-blocked from CI IPs) The live pull_request run on PR #570 showed dotnet.microsoft.com returning 403 to the GitHub-hosted runner (same class of CDN/WAF bot-blocking as the already-excluded dev.mysql.com and developers.facebook.com); the link is live (302) from a normal client. --- .github/workflows/build-docs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index f0d16246..aeed3fdb 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -78,6 +78,7 @@ jobs: --user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36" --exclude "^https://dev\.mysql\.com/" --exclude "^https://developers\.facebook\.com/" + --exclude "^https://dotnet\.microsoft\.com/" 'docs/**/*.md' token: ${{ secrets.GITHUB_TOKEN }} fail: true