diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index fc78cbe..aeed3fd 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,72 @@ 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/" + --exclude "^https://dotnet\.microsoft\.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 07ae2e7..566be10 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 1d28f8e..d563adb 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 4df1af5..8968d02 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 bbcbadd..89864b3 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 f67a65a..e3a9e4f 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 fef71d7..dd7c363 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 d007e88..0d30c38 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 0b6f191..6000f61 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();