Skip to content
Notifications
Clear all

Just built an internal wiki updater that runs after every product release.

1 Posts
1 Users
0 Reactions
2 Views
(@cloud_infra_vet)
Reputable Member
Joined: 2 months ago
Posts: 134
Topic starter   [#19823]

Our product release cycles have accelerated to the point where our internal Confluence wiki was perpetually stale. Documentation lag was creating real friction for support and onboarding. The classic "wiki garde" role was a rotating burden nobody wanted, and manual updates were error-prone. I architected a system to automate this, treating the wiki as a managed resource, not a manual artifact.

The core concept is an event-driven pipeline triggered by our CI/CD completion. When a release job in Jenkins succeeds, it publishes a message to an Amazon EventBridge bus. This event contains a payload with the new version number, a link to the release notes in the repository, and the changed module paths. A Lambda function, written in Python, is invoked by this event. Its responsibilities are:
1. Parse the event and fetch detailed change data from the Git API (using the module paths).
2. Use the Confluence REST API to locate the target parent page for "Release Notes."
3. Create or update a child page under that parent for the specific version.

The Lambda function uses the `atlassian-python-api` library. I implemented idempotency by using the version string in the page title; a lookup is performed first to update existing pages if the pipeline runs twice. The function also tags the page with metadata (e.g., `release-version: 2.5.1`) for future automation hooks.

```python
import boto3
from atlassian import Confluence
import os

def lambda_handler(event, context):
version = event['detail']['version']
changes = fetch_changes_from_git(event['detail']['commit_range'])

confluence = Confluence(
url=os.environ['CONFLUENCE_URL'],
username=os.environ['CONFLUENCE_USER'],
password=os.environ['CONFLUENCE_API_KEY']
)

parent_page_id = confluence.get_page_id('SPACE', 'Product Release Notes')
page_title = f"Release v{version}"

# Check for existing page
existing_page = confluence.get_page_by_title('SPACE', page_title)

content = f"""

Changes in Version {version}

    {"".join([f'

  • {change}
  • ' for change in changes])}

Automatically updated via release pipeline.

"""

if existing_page:
confluence.update_page(
page_id=existing_page['id'],
title=page_title,
body=content
)
print(f"Updated page for {version}")
else:
confluence.create_page(
space='SPACE',
title=page_title,
body=content,
parent_id=parent_page_id
)
print(f"Created page for {version}")
```

Infrastructure is defined in Terraform, managing the EventBridge rule, Lambda function, IAM roles with least-privilege policies (specific secrets for Confluence API are stored in AWS Secrets Manager), and a CloudWatch log group. The Terraform module ensures the Lambda is deployed as a container image from ECR for easier dependency management.

Key considerations and pitfalls we addressed:
* **Confluence API Rate Limiting:** Implemented exponential backoff and retry logic in the Lambda.
* **Idempotency:** Crucial to prevent duplicate pages from retries or pipeline re-runs.
* **Security:** The Lambda runs in a private VPC with a NAT gateway for egress to Confluence Cloud. The Confluence API key has permissions scoped only to create/edit pages in the specific space.
* **Failure Handling:** Failed Lambda invocations (e.g., Confluence downtime) are sent to a Dead-Letter Queue (SQS) for investigation and manual replay.

The operational cost is negligible—a few million EventBridge events and Lambda invocations per month fall well within the free tier. The real ROI is eliminating ~8 person-hours of manual toil per release cycle and ensuring documentation is always synchronized. This pattern is now being adapted for other automated documentation updates, such as updating runbooks when Terraform module outputs change.



   
Quote