From aa71abe190d3d485313c1f139f20e42126827fe5 Mon Sep 17 00:00:00 2001 From: nojaf Date: Sat, 11 Nov 2023 12:10:30 +0100 Subject: [PATCH 1/3] Initial batch of users of FSharp.Formatting. --- FSharp.Formatting.sln | 1 + docs/users.md | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 docs/users.md diff --git a/FSharp.Formatting.sln b/FSharp.Formatting.sln index 76b0b62a2..ab9ed9460 100644 --- a/FSharp.Formatting.sln +++ b/FSharp.Formatting.sln @@ -33,6 +33,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{312E452A-1 docs\markdown.fsx = docs\markdown.fsx docs\styling.md = docs\styling.md docs\upgrade.md = docs\upgrade.md + docs\users.md = docs\users.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "templates", "templates", "{D0550510-0DCE-4B40-B4FB-091668E1C5FD}" diff --git a/docs/users.md b/docs/users.md new file mode 100644 index 000000000..b43dc684e --- /dev/null +++ b/docs/users.md @@ -0,0 +1,36 @@ +--- +category: Documentation +categoryindex: 1 +index: 8 +--- +# Users of FSharp.Formatting + +The FSharp.Formatting documentation tool is widely used within the F# community. +Here is a non-exhaustive list of projects: + + + + +| Project name | | Repository | Note | +|-----------------------------------------------------------------------------|:--|--------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------| +| [FSharp.Formatting](https://fsprojects.github.io/FSharp.Formatting/) | | [https://github.com/fsprojects/FSharp.Formatting/](https://github.com/fsprojects/FSharp.Formatting/) | | +| [F# compiler guide](https://fsharp.github.io/fsharp-compiler-docs/) | | [https://github.com/dotnet/fsharp/](https://github.com/dotnet/fsharp/) | The documentation is generated and published from [https://github.com/fsharp/fsharp-compiler-docs](https://github.com/fsharp/fsharp-compiler-docs) | +| [F# Core Library Documentation](https://fsharp.github.io/fsharp-core-docs/) | | [https://github.com/dotnet/fsharp/](https://github.com/dotnet/fsharp/) | The documentation is generated and published from [https://github.com/fsharp/fsharp-core-docs](https://github.com/fsharp/fsharp-core-docs) | +| [FsLexYacc](https://fsprojects.github.io/FsLexYacc) | | [https://github.com/fsprojects/fslexYacc/](https://github.com/fsprojects/fslexYacc/) | | +| [FSharp.Data](https://fsprojects.github.io/FSharp.Data/) | | [https://github.com/fsprojects/FSharp.Data/](https://github.com/fsprojects/FSharp.Data/) | | +| [Plotly.NET](https://plotly.net/) | | [https://github.com/plotly/Plotly.NET](https://github.com/plotly/Plotly.NET) | | +| [FSharp.Stats](https://fslab.org/FSharp.Stats/) | | [https://github.com/fslaborg/FSharp.Stats/](https://github.com/fslaborg/FSharp.Stats/) | | +| [FsHttp](https://fsprojects.github.io/FsHttp/) | | [https://github.com/fsprojects/FsHttp/](https://github.com/fsprojects/FsHttp/) | | +| [Fantomas](https://fsprojects.github.io/fantomas/docs/) | | [https://github.com/fsprojects/fantomas/](https://github.com/fsprojects/fantomas/) | | +| [Telplin](https://nojaf.com/telplin/docs/) | | [https://github.com/nojaf/telplin/](https://github.com/nojaf/telplin/) | | +| [FSharp.Data.Fred](https://github.com/nhirschey/FSharp.Data.Fred/) | | [https://github.com/nhirschey/FSharp.Data.Fred/](https://github.com/nhirschey/FSharp.Data.Fred/) | | +| [N Hirschey Teaching](https://nhirschey.github.io/Teaching/) | | [https://github.com/nhirschey/Teaching](https://github.com/nhirschey/Teaching) | | +| [FsUnit](https://fsprojects.github.io/FsUnit/) | | [https://github.com/fsprojects/FsUnit](https://github.com/fsprojects/FsUnit) | | +| [FAKE](https://fake.build/) | | [https://github.com/fsprojects/FAKE](https://github.com/fsprojects/FAKE) | | +| [FSharp.Data.GraphQL](https://fsprojects.github.io/FSharp.Data.GraphQL/) | | [https://github.com/fsprojects/FSharp.Data.GraphQL](https://github.com/fsprojects/FSharp.Data.GraphQL) | | From 29a75be3dd13bdcd785b222f8e274e81b794f2f3 Mon Sep 17 00:00:00 2001 From: nojaf Date: Sun, 12 Nov 2023 15:52:05 +0100 Subject: [PATCH 2/3] From zero to hero: deploying to GitHub Pages --- FSharp.Formatting.sln | 1 + docs/content/img/github-pages-settings.png | Bin 0 -> 33534 bytes docs/zero-to-hero.md | 261 +++++++++++++++++++++ 3 files changed, 262 insertions(+) create mode 100644 docs/content/img/github-pages-settings.png create mode 100644 docs/zero-to-hero.md diff --git a/FSharp.Formatting.sln b/FSharp.Formatting.sln index ab9ed9460..dcbafb0a0 100644 --- a/FSharp.Formatting.sln +++ b/FSharp.Formatting.sln @@ -34,6 +34,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{312E452A-1 docs\styling.md = docs\styling.md docs\upgrade.md = docs\upgrade.md docs\users.md = docs\users.md + docs\zero-to-hero.md = docs\zero-to-hero.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "templates", "templates", "{D0550510-0DCE-4B40-B4FB-091668E1C5FD}" diff --git a/docs/content/img/github-pages-settings.png b/docs/content/img/github-pages-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..a7657705daa724182a7158891b44660fd41f9a39 GIT binary patch literal 33534 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≪zkbrk9J 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 dotnet fsdocs watch + +Open [http://localhost:8901](http://localhost:8901) and you should see our first page! + +🪄 You might notice that there are some images missing. You can add these in the `docs` folder in the right location. + +## Generating API documentation + +By default, `fsdocs` will generate API documentation for the configured `--projects`. +When this flag is not specified, `fsdocs` will look for solutions or projects in the working directory. +It will filter these found projects, the requirements are: + +- Having `library` +- Having a binary, so you need to build your project first before the documentation can be generated. +- Not having `true` +- Having `true` + +🪄 If you made some changes to in order to adhere to the rules, you may want to remove the `.fsdocs/cache` file. + +## Adding the missing properties + +After our initial `watch` run, you may have noticed that some links aren't working yet. +`License`, `Releases Notes` and `Source Repository` can be provided by setting MSBuild properties. + +You can either add these properties to a single `.fsproj` file, or more typically, add them to a [Directory.Build.props](https://learn.microsoft.com/visualstudio/msbuild/customize-by-directory) file. +The simplest `Directory.Build.props` file: + +```xml + + + https://github.com/fsprojects/FSharp.AWS.DynamoDB + https://github.com/fsprojects/FSharp.AWS.DynamoDB/blob/master/License.md + https://github.com/fsprojects/FSharp.AWS.DynamoDB/blob/master/RELEASE_NOTES.md + https://fsprojects.github.io/FSharp.AWS.DynamoDB + + +``` + +🪄 If you don't have any release notes yet, you could consider using [Ionide.KeepAChangelog](https://github.com/ionide/KeepAChangelog). + +Running `dotnet fsdocs watch` will now yield: + +``` + root --> https://github.com/fsprojects/FSharp.AWS.DynamoDB/ + ... + fsdocs-license-link --> https://github.com/fsprojects/FSharp.AWS.DynamoDB/blob/master/License.md + fsdocs-release-notes-link --> https://github.com/fsprojects/FSharp.AWS.DynamoDB/blob/master/RELEASE_NOTES.md + ... + fsdocs-repository-link --> https://github.com/fsprojects/FSharp.AWS.DynamoDB/ +``` + +⚠️ Again, you might need to remove `.fsdocs/cache` in order for changes to be picked up! + +`` is actually a very important property when you run `dotnet fsdocs build`. +`build` will generated static files for the targeted production environment. In our case, this will be GitHub Pages. + +Pages will host your files from https://github.com/user/project to on `https://user.github.io/project/` by default. +You can change this by adding a custom domain so we need to be sure that all links and urls will be generated correctly during a build. + +Let's now run `dotnet fsdocs build`. + +`` will replace the `{{root}}` substitution, which is used all over the place in the default template. + +⚠️ You want to ensure that the static files in the `output` folder (after running the build) have the correct links. + +## Ignore generated files + +Alright, at this point we've made a lot of progress. I you are using `git` you want to add the following to your [.gitignore](https://git-scm.com/docs/gitignore) file. + +```.ignorelang +# FSharp.Formatting +.fsdocs/ +output/ +tmp/ +``` + +## Ship it! + +Once we are satisfied with our documentation, we want to publish it to GitHub Pages. +We can use [GitHub Actions](https://github.com/features/actions) to deploy our website. + +Deploy to Pages from GitHub Actions must be enabled in the repository settings: + +![Enable deploy from Actions](./content/img/github-pages-settings.png) + +The typical flow is to publish your documentation after a release or after new commits were added to the default branch. +Let's create a very basic Action that will deploy our website after pushing to main: + +Create a file `.github/workflows/docs.yml`: + +```yml +name: Docs + +# Trigger this Action when new code is pushed to the main branch +on: + push: + branches: + - main + +# We need some permissions to publish to Github Pages +permissions: + contents: write + pages: write + id-token: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + # Checkout the source code + - uses: actions/checkout@v4 + # Setup dotnet, please use a global.json to ensure the right SDK is used! + - name: Setup .NET + uses: actions/setup-dotnet@v3 + # Restore the local tools + - name: Restore tools + run: dotnet tool restore + # Build the code for the API documentation + - name: Build code + run: dotnet build -c Release YourSolution.sln + # Generate the documentation files + - name: Generate the documentation' + run: dotnet fsdocs build --properties Configuration=Release + # Upload the static files + - name: Upload documentation + uses: actions/upload-pages-artifact@v2 + with: + path: ./output + + # GitHub Actions recommends deploying in a separate job. + deploy: + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 +``` + +⚠️ Careful yaml is indentation sensitive! + +## Next steps + +Mission accomplished right? If everything went well, you should have a published website at this point! +Here are some next steps you could consider: + +### Use fsx file in your documentation + +Create documentation using [Literate Scripts](../literate.html). A typical flow here is that you load your locate project binary into a script and create examples using the latest code: + +```fsharp +#r "../src/Project1/bin/Debug/net6.0/Project1.dll" + +open Project1 + +// Actual consumption of your project! +let result = SomeType.SomeMethod("foo") +``` + +When using the `--strict` flag in `dotnet fsdocs build`, your documentation generation will fail if your script contains errors. +This is useful to ensure your documentation is always in sync with your latest public API! + +### Automatically update to newer versions of fsdocs-tool + +Using [Dependabot](https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates) you can easily receive new PR's with updates to your `dotnet` dependencies. + +Create a `github/dependabot.yml` file with: + +```yml +version: 2 +updates: + # Update to newer version of GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + + # Update to newer NuGet dependencies + - package-ecosystem: "nuget" + directory: "/" + schedule: + interval: "daily" +``` + +This will automatically create a new PR when there is an update to the `fsdocs` tool. + +⚠️ P️lease be very careful, if you have followed along, we don't have any GitHub Actions right now that run against pull requests! +It is recommended to have an Action that builds your documentation against any incoming changes. +You typically want to lint code, run unit tests and perform other useful checks as well! + +Example Action, `.github/workflows/ci.yml`: +```yml +name: CI + +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Setup .NET Core + uses: actions/setup-dotnet@v3 + - name: Restore tools + run: dotnet tool restore + - name: Build + run: dotnet build YourSolution.sln + - name: Documentation + run: dotnet fsdocs build +``` + +⚠️ Also never trust any update to `fsdocs` blindly, always check the [release notes](https://github.com/fsprojects/FSharp.Formatting/blob/main/RELEASE_NOTES.md) to see if there are any breaking changes. From 8347a85aa8fee2d72e5ce8e0de299de4a0730ecd Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Mon, 13 Nov 2023 08:25:39 +0100 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: dawe --- docs/zero-to-hero.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/zero-to-hero.md b/docs/zero-to-hero.md index c7aaf3445..2234a3407 100644 --- a/docs/zero-to-hero.md +++ b/docs/zero-to-hero.md @@ -5,7 +5,7 @@ index: 9 --- # From zero to hero: deploying to GitHub Pages -This guide is meant for a typically setup for open-source projects on GitHub. +This guide is meant for a typical setup of open-source projects on GitHub. We start from a repository without any documentation and aim to end up with a published website on [GitHub Pages](https://pages.github.com/). ## Install the local tool @@ -44,7 +44,7 @@ When `fsdocs` runs, it will transform this `index.md` file to `index.html`, whic We can put `# Hello world` in the markdown file for now. -Having this in play, should already serve the first page when we start the `watch` command: +Having this in place, should already serve the first page when we start the `watch` command: > dotnet fsdocs watch @@ -63,7 +63,7 @@ It will filter these found projects, the requirements are: - Not having `true` - Having `true` -🪄 If you made some changes to in order to adhere to the rules, you may want to remove the `.fsdocs/cache` file. +🪄 If you made some changes in order to adhere to the rules, you may want to remove the `.fsdocs/cache` file. ## Adding the missing properties @@ -100,9 +100,9 @@ Running `dotnet fsdocs watch` will now yield: ⚠️ Again, you might need to remove `.fsdocs/cache` in order for changes to be picked up! `` is actually a very important property when you run `dotnet fsdocs build`. -`build` will generated static files for the targeted production environment. In our case, this will be GitHub Pages. +`build` will generate static files for the targeted production environment. In our case, this will be GitHub Pages. -Pages will host your files from https://github.com/user/project to on `https://user.github.io/project/` by default. +Pages will host your files from https://github.com/user/project on `https://user.github.io/project/` by default. You can change this by adding a custom domain so we need to be sure that all links and urls will be generated correctly during a build. Let's now run `dotnet fsdocs build`. @@ -113,7 +113,7 @@ Let's now run `dotnet fsdocs build`. ## Ignore generated files -Alright, at this point we've made a lot of progress. I you are using `git` you want to add the following to your [.gitignore](https://git-scm.com/docs/gitignore) file. +Alright, at this point we've made a lot of progress. If you are using `git` you want to add the following to your [.gitignore](https://git-scm.com/docs/gitignore) file. ```.ignorelang # FSharp.Formatting @@ -189,7 +189,7 @@ jobs: ## Next steps -Mission accomplished right? If everything went well, you should have a published website at this point! +Mission accomplished, right? If everything went well, you should have a published website at this point! Here are some next steps you could consider: ### Use fsx file in your documentation