This action is in development, and should not be used except on repositories that are part of our development and testing programme.
The action is still in alpha, and breaking changes could occur.
This action automates syncing of documentation between a docs
folder in a
repository and discourse, which is how the charm documentation is published to
charmhub.
In particular, the action does:
docs
folder in a given PR does not conflict with external contributions in
DiscourseIn its operation, the action will manage a tag (named
discourse-gatekeeper/content
), that represents the last synced content with
Discourse. Please do not remove this tag to ensure correct execution of the
action.
The action can be included in your CI/CD pipeline by adding the following step
- name: Publish documentation
uses: canonical/discourse-gatekeeper@stable
id: publishDocumentation
with:
discourse_host: discourse.charmhub.io
discourse_api_username: ${{ secrets.DISCOURSE_API_USERNAME }}
discourse_api_key: ${{ secrets.DISCOURSE_API_KEY }}
github_token: ${{ secrets.GITHUB_TOKEN }}
dry_run: "true" // "false"
This action requires an API username and key to discourse. For Canonical staff, please file a ticket with IS to request one. Note that there is a rate limit on the number of topics that can be created by a user per day on discourse.
There is a parameter, dry_run
, which will do everything except
make changes on discourse and log what would have happened. This is the
recommended use to enable one-way sync where the content in the repository is
kept in sync with Discourse but where no upload is allowed.
:warning: Two-way sync between Discourse and Github is currently not allowed and can only be used with leadership approval.
Make sure that the action runs in workflow with correct permission settings. In particular, the action should be allowed to:
discourse-gatekeeper/migrate
,
as well update the position of the discourse-gatekeeper/content
tag. Thus, when the action is embedded in an external workflow, make sure that you pass credentials and permissions accordingly, e.g.
sync-docs:
uses: ./.github/workflows/sync_docs.yaml
secrets: inherit
permissions:
contents: write
pull-requests: write
Although the action is designed to always perform Raise, Check and Upload functions, for best user-experience, we suggest the action to be included in:
discourse-gatekeeper/content
tag is
updated regularly The action is currently in alpha state. If you encounter any issue with secrets, permissions or execution, the action will fail and report that as the reason. It may help to space out adopting this action if you are planning to use it for multiple charms or to use different users for each charm.
Note that other rate limits also apply which is why execution might look like it is stalled for a short period and then resume. The action will gracefully wait in case of throttling up to a maximum of 10 minutes.
Depending on the status of your project, you may have your documentation either in Discourse or in GitHub already. If you don't have any documentation, we recommend that you start including your documentation in Discourse first, as this is generally the source of truth, and the primary platform where the documentation is exposed and fetch by frontend platforms, e.g. Charmhub.
In the following, we outline the process to enable Discourse Gatekeeper, depending on whether:
docs
key in metadata.yaml
with the link to the documentation on
charmhub.metadata.yaml
in your main branch, trigger the action
manually or via automated processes (either in the CI or in the release
pipeline)discourse-gatekeeper/migrate
will
be created and a pull request named [discourse-gatekeeper] Migrate charm docs
will be created targeting the default branch of the repository. In order to
ensure that the branches can be created successfully, please make sure that
there are no existing branches clashing with the name above. Please note
that the dry_run
input has no effect on migrate mode.The action will now compare the discourse topics with the files and directories
under the docs
directory and make any changes based on differences.
Additional recommended steps:
edge
to see what changes to
the documentation will be made once you publish to stable
.:warning: Note that this requires content to be pushed to Discourse, and therefore cannot be used without explicit approval from leadership
docs
folder in the repository.docs/index.md
for any content you would like to
display above the navigation table on discourse. This content does not get
published to charmhub and is only visible on discourse.docs
folder, create directories for page groups (e.g., for all
tutorials) and markdown files (*.md
) for individual pages. On charmhub,
the groupings on the navigation panel will be named based on the name of
the directory after replacing _
and -
with spaces and appliying the
str.title
function to it. The name of pages is based on whatever of the following is
available, in order: (1) the first level 1 heading (e.g., # <heading>
) in
the file, the first line in the file or the name of the file treated in the
same way as the name of groupings.
Note that the action may change the order of how groups and pages are
displayed in the navigation pane. The action will sort them alphabetically.docs
key from metadata.yaml
if you would
like the action to create its own topics on discourse rather than reuse
any existing topics. This means that if, for some reason, you don't like
what the action does, you can easily revert back to the previous
documentation. Be sure to file an issue with the reason if the action does
something unexpected or you would prefer it to do something different.Trigger the action manually or via automated processes (either in the CI or in the release pipeline). We also suggest you to include a log of the created URLs as part of the action, e.g.
steps:
...
- id: publishDocumentation
uses: canonical/discourse-gatekeeper@stable
- name: Show index page
run: echo '${{ steps.publishDocumentation.outputs.index_url }}'
...
index_url
output of the action. This needs to
be added to the metadata.yaml
under the docs
key.To ensure that contributions to the documentation on discourse are not overridden, the action compares the content that was last pushed to discourse with the current documentation on discourse and any proposed changes. If there are changes both on discourse and in the repository, the action will prompt you to resolve those conflicts by editing the documentation on discourse and on the repository. Be sure to explain the reasoning for any changes on discourse.
The content that was last pushed to discourse is determined by getting the
content from a given file from a commit with the
discourse-gatekeeper/base-content
tag. If the tag does not exist, the action will
fail and request for the tag to be created.
In addition to page-by-page conflict detection, the action will check whether there are both (1) unmerged community contributions and (2) proposed documentation changes in a given PR. If both are true even if there are no page-by-page conflicts, the action will ask that the community contributions are merged first and any logical conflicts are resolved between the proposed new documentation and the changes on discourse.
For example, if there are community contributions on docs/getting-started.md
that have not been merged into main
and a PR proposes changes to
docs/architecture.md
, this will be considered a conflict as the change to
docs/architecture.md
could make changes to the documentation that mean that
the changes to docs/getting-started.md
are no longer accurate.
The docs/index.md
file may contain a # contents
section which is used to
customize the generation of the navigation table on discourse. Everything from
this section up to the next header (identified by a line starting with #
) or
the end of the file will be removed from the index page and be replaced with the
navigation table on discourse. For example the following section in
docs/index.md
:
# Contents
1. [Reference](reference)
1. [Integrations](reference/integrations.md)
Would result in the following navigation table on discourse:
# Navigation
| level | path | navlink |
| --- | --- | --- |
| 1 | reference | [Reference]() |
| 2 | reference-integrations | [Integrations](/t/nginx-ingress-integrator-docs-reference-integrations/7756) |
The following are example valid permutations of the contents section in
index.md
:
# Contents
1. [Reference](reference)
a. [Integrations](reference/integrations.md)
# Contents
* [Reference](reference)
* [Integrations](reference/integrations.md)
# Contents
- [Reference](reference)
- [Integrations](reference/integrations.md)
# Contents
- [Reference](reference)
1. [Integrations](reference/integrations.md)
The links can be one of the following:
tutorials
directory)tutorials/getting-started.md
file)*.md
files and directories in docs
not listed in the contents index will be
added in alphabetical order after any items that are listed. This is to ensure
backwards compatibility. References are checked for validity. A link to a file
or directory that does not exist will result in an error.
Items on the contents index can be commented out which will mean the item on the navigation table won't have a level. This will mean that the item is not shown on the navigation but can still be used in links.
This action uses the notion of risks, similarly to what used in SNAP (see here for a description and explanation of these concepts). We currently only provide support on one single track (say latest), with the following branching naming convention:
We therefore generally advise you to pick the risk channel that best fits to your need.
When merging a PR, we make sure the code follows all code conventions (linting), unit-tests and integration tests. Edge version are however NOT checked against full end-to-end integration tests.
End-to-End tests are implemented in a separated test repository, and run as scheduled workflows against the edge branch. When working on large and impactful feature, we generally suggest to test your branch PR against End-to-End tests even before merging. To do so, follow these steps:
name: Publish documentation
uses: canonical/discourse-gatekeeper@your-pr-branch # CHANGE HERE
Periodically, we review the latest changes on edge branches and we rebase lower risks branches (e.g. stable) onto higher risk branches (e.g. edge).