Modern software teams have become very good at automating builds, tests, deployments, and infrastructure. Yet one part of the release process often remains surprisingly manual: documentation.
After every release, someone usually has to:
- Write release notes
- Update documentation
- Capture screenshots
- Record a short product walkthrough
- Notify the team
None of these tasks are technically difficult, but together they consume a significant amount of engineering time.
In one of our internal projects, we started treating documentation as another artifact produced by the build pipeline rather than a separate task performed after development.
This article describes the workflow we built and the lessons we learned along the way.
Why Documentation Becomes Outdated
One common problem is that documentation lives separately from the code.
Developers update APIs.
Product managers update documentation.
Designers update screenshots.
Eventually these versions drift apart.
The result is documentation that is technically correct but no longer reflects the current application.
We wanted documentation to be generated from the same source that powers the application.
Architecture
Our workflow looks like this:
Developer Push│▼GitHub Actions│▼Build Application│▼Run Tests│▼Extract Feature Metadata│▼Generate Markdown│▼Publish Documentation
Every release generates documentation automatically.
No manual copy-and-paste.
No forgotten release notes.
Step 1 — Exposing Feature Metadata
Instead of writing release notes manually, we expose release information through a Minimal API.
app.MapGet("/api/releases", () =>{return Results.Ok(new[]{new Release("Dashboard Analytics","Added","Real-time usage metrics"),new Release("Export","Updated","CSV export performance improved")});});public record Release(string Feature,string Status,string Description);
This endpoint becomes the single source of truth.
Step 2 — Generate Markdown
A small console application converts JSON into Markdown.
var releases =await httpClient.GetFromJsonAsync<List<Release>>("/api/releases");var builder = new StringBuilder();builder.AppendLine("# Release Notes");builder.AppendLine();foreach (var item in releases){builder.AppendLine($"## {item.Feature}");builder.AppendLine($"- Status: {item.Status}");builder.AppendLine($"- {item.Description}");builder.AppendLine();}await File.WriteAllTextAsync("ReleaseNotes.md",builder.ToString());
Because everything is generated, documentation always matches the deployed application.
Step 3 — Automating with GitHub Actions
Once Markdown generation works locally, adding it to CI is straightforward.
name: Release Documentationon:push:branches:- mainjobs:docs:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4- uses: actions/setup-dotnet@v4with:dotnet-version: 9.0.x- run: dotnet restore- run: dotnet build- run: dotnet run --project tools/ReleaseGenerator
Every merge now produces updated release documentation automatically.
Adding Visual Context
One lesson became obvious very quickly.
Text explains APIs well.
It does not always explain user experience.
When product managers reviewed new features, many discussions revolved around UI behavior rather than technical implementation.
To solve this, we began creating short visual prototypes before recording polished demonstrations.
For one internal experiment, we testedKling 3.0 AI Video Generator to generate several rough visual concepts for feature walkthroughs. The generated clips were never published directly. Instead, they helped the team compare different presentation styles before investing time in editing a final release video.
The value wasn't automation itself.
The value was receiving feedback much earlier.
Lessons Learned
After several releases, we noticed a few patterns.
1. Documentation should be generated, not maintained
Whenever documentation requires manual updates, it eventually falls behind.
Generating documentation from structured data dramatically reduces that risk.
2. Early visual feedback saves engineering time
A rough prototype often answers questions long before a polished demo exists.
Teams spend less time discussing abstract ideas because everyone can see the same concept.
3. Keep automation simple
Our first pipeline attempted to automate everything.
It quickly became difficult to maintain.
Today, the pipeline focuses on repetitive work only.
Anything requiring judgment still receives manual review.
4. Documentation is part of the product
Developers often think of documentation as something written after implementation.
In reality, documentation influences onboarding, support requests, and product adoption just as much as the application itself.
What We Would Improve Next
If we rebuilt this workflow today, we would probably:
- Generate API examples automatically from OpenAPI.
- Produce architecture diagrams during CI.
- Validate Markdown links before publishing.
- Generate changelog summaries for different audiences.
- Integrate release assets directly into internal documentation portals.
Final Thoughts
CI/CD has changed the way we build software.
Infrastructure is automated.
Testing is automated.
Deployments are automated.
Documentation deserves the same attention.
Not because developers enjoy writing release notes, but because accurate documentation improves communication across engineering, product, QA, and customer support.
The biggest improvement in our workflow wasn't generating content faster.
It was making reliable information available immediately after every release.









