Source-of-truth repository for Zendesk Guide knowledgebase articles. Articles are stored as Markdown files with YAML frontmatter and synced to Zendesk Guide via GitHub Actions.
articles/
category-slug/
section-slug/
article-slug.md # One file per Zendesk Guide article
scripts/
config.py # Environment variable loading
export.py # Zendesk → Repo export tool
sync.py # Repo → Zendesk sync tool
validate.py # Article validation (used in CI)
zendesk_client.py # Zendesk API client
markdown_utils.py # HTML ↔ Markdown conversion
.github/workflows/
sync.yml # Push-to-main sync workflow
validate.yml # PR validation workflow
Each article is a Markdown file with YAML frontmatter:
---
zendesk_article_id: 123456789
title: "How to Reset Your Password"
author_id: 987654321
labels:
- password
- security
position: 3
locale: "en-us"
created_at: "2024-01-15T10:30:00Z"
updated_at: "2024-06-20T14:22:00Z"
section_id: 456789
category_id: 789012
---
Article content here...The folder path determines the Zendesk category and section:
articles/{category-slug}/{section-slug}/{article-slug}.md
- Python 3.10+
- A Zendesk account with API access enabled
- A Zendesk API token (how to generate one)
-
Clone the repository:
git clone <repo-url> cd support-knowledgebase
-
Install dependencies:
pip install -r requirements.txt
-
Create a
.envfile from the template:cp .env.example .env
-
Edit
.envwith your Zendesk credentials:ZENDESK_SUBDOMAIN=yourcompany ZENDESK_EMAIL=your-email@example.com ZENDESK_API_TOKEN=your-api-token
Add the following secrets to your GitHub repository (Settings → Secrets and variables → Actions):
| Secret | Description |
|---|---|
ZENDESK_SUBDOMAIN |
Your Zendesk subdomain (e.g. yourcompany) |
ZENDESK_EMAIL |
Email of the Zendesk user for API authentication |
ZENDESK_API_TOKEN |
Zendesk API token |
Pull all published articles from your Zendesk Guide into the articles/ directory:
python scripts/export.pyOptions:
| Flag | Description | Default |
|---|---|---|
--locale |
Zendesk locale to export | en-us |
--output-dir |
Output directory | articles |
--verbose, -v |
Enable debug logging | |
--quiet, -q |
Suppress non-error output |
This is designed as an on-demand tool. Run it for the initial migration, or whenever you need to re-import content that was edited directly in Zendesk.
Push local changes to Zendesk. This is normally run automatically by the GitHub Actions workflow, but can also be run locally:
# Sync specific files
python scripts/sync.py articles/getting-started/setup/install-guide.md
# Sync all articles
python scripts/sync.py --full
# Dry run (preview without making changes)
python scripts/sync.py --dry-run --full
# Handle deleted files
python scripts/sync.py --deleted articles/old-category/old-section/removed-article.mdOptions:
| Flag | Description | Default |
|---|---|---|
--full |
Sync all articles instead of specific files | |
--dry-run |
Preview changes without calling the API | |
--deleted |
Files that were deleted (archives in Zendesk) | |
--articles-dir |
Articles directory | articles |
--locale |
Zendesk locale | en-us |
--verbose, -v |
Enable debug logging | |
--quiet, -q |
Suppress non-error output |
Check that all article files are well-formed:
python scripts/validate.pyThis runs automatically on pull requests via GitHub Actions.
Trigger: Push to main that modifies files in articles/, or manual dispatch.
- Detects which article files were added, modified, or deleted in the commit.
- Runs
sync.pyto push changes to Zendesk. - If new articles were created, commits the updated frontmatter (with new Zendesk article IDs) back to the repo.
Manual full sync: Go to Actions → "Sync Articles to Zendesk" → Run workflow → set full_sync to true.
Trigger: Pull requests that modify files in articles/.
Validates:
- YAML frontmatter is parseable and has required fields
- Article body is not empty
- Folder structure follows
category/section/article.mdpattern - File and folder names are valid URL slugs
- No duplicate
zendesk_article_idvalues
- Create a new
.mdfile in the appropriatearticles/{category}/{section}/folder. - Add frontmatter with at least a
titlefield. Leavezendesk_article_idempty or omit it. - Write the article body in Markdown.
- Open a PR. The validate workflow will check your article.
- Merge to
main. The sync workflow will create the article in Zendesk and commit the new article ID back.
Example:
---
title: "New Feature Guide"
labels:
- feature
- guide
position: 5
---
This is a guide to the new feature...- Edit the
.mdfile directly in the repo. - Open a PR and merge to
main. - The sync workflow updates the corresponding Zendesk article.
- Delete the
.mdfile from the repo. - Merge to
main. - The sync workflow archives (unpublishes) the article in Zendesk.
- Zendesk credentials are never stored in the repository.
- Local development uses a
.envfile (excluded via.gitignore). - CI/CD uses GitHub repository secrets.
- The sync workflow only runs on pushes to
main, not on PRs from forks. - The validation workflow does not access any secrets.