Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/blog/** @MichaelCade

13 changes: 13 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/blog_post.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Blog Post Submission

### Summary

Describe your post in 2-4 sentences.

### Checklist

- [ ] I added my post under `blog/posts/` with filename format `YYYY-MM-DD-short-title.md`
- [ ] I used the metadata schema from `blog/_template.md` (`title`, `author`, `date`, `tags`, `summary`)
- [ ] My post is original and relevant to the 90DaysOfDevOps community topics
- [ ] I verified local markdown links and image paths
- [ ] I have read and followed `CONTRIBUTING.md`
110 changes: 110 additions & 0 deletions .github/workflows/blog-post-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Blog Post Validation

on:
pull_request:
paths:
- "blog/posts/*.md"
- "blog/_template.md"

permissions:
contents: read

jobs:
validate-blog-posts:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Collect changed blog posts
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
git diff --name-only "$BASE_SHA" "$HEAD_SHA" -- 'blog/posts/*.md' > changed_blog_posts.txt
echo "Changed posts:"
cat changed_blog_posts.txt || true

- name: Validate metadata and local links
run: |
python - <<'PY'
from pathlib import Path
from datetime import datetime
import re
import sys

changed_file_list = Path("changed_blog_posts.txt")
changed_files = []
if changed_file_list.exists():
changed_files = [line.strip() for line in changed_file_list.read_text(encoding="utf-8").splitlines() if line.strip()]

if not changed_files:
print("No changed blog post files detected.")
raise SystemExit(0)

required_fields = ["title", "author", "date", "tags", "summary"]
all_errors = []

for rel_path in changed_files:
path = Path(rel_path)
if not path.exists():
continue

text = path.read_text(encoding="utf-8")
lines = text.splitlines()
errors = []

if not lines or lines[0].strip() != "---":
errors.append("Missing YAML front matter opening delimiter '---'.")
else:
end_idx = None
for idx in range(1, len(lines)):
if lines[idx].strip() == "---":
end_idx = idx
break
if end_idx is None:
errors.append("Missing YAML front matter closing delimiter '---'.")
front_matter_lines = []
else:
front_matter_lines = lines[1:end_idx]

if end_idx is not None:
front_matter_text = "\n".join(front_matter_lines)
for field in required_fields:
if not re.search(rf"(?m)^{field}\s*:", front_matter_text):
errors.append(f"Missing required metadata field: {field}")

date_match = re.search(r'(?m)^date\s*:\s*"?(.*?)"?\s*$', front_matter_text)
if date_match:
date_value = date_match.group(1).strip()
try:
post_date = datetime.strptime(date_value, "%Y-%m-%d").date()
if post_date > datetime.now().date():
errors.append("Date cannot be in the future.")
except ValueError:
errors.append("Invalid date format. Expected YYYY-MM-DD.")

for link in re.findall(r"\[[^\]]+\]\(([^)]+)\)", text):
target = link.strip()
if not target or target.startswith(("http://", "https://", "mailto:", "#")):
continue
target = target.split("#", 1)[0].split("?", 1)[0]
if not target:
continue
resolved = (path.parent / target).resolve()
if not resolved.exists():
errors.append(f"Broken local link: {link}")

if errors:
all_errors.append(f"{rel_path}:")
all_errors.extend([f" - {err}" for err in errors])

if all_errors:
print("Validation failed:\n")
print("\n".join(all_errors))
sys.exit(1)

print("All changed blog posts passed metadata and local link validation.")
PY
28 changes: 28 additions & 0 deletions .github/workflows/deploy-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Deploy GitHub Pages

on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: write

concurrency:
group: ${{ github.repository }}-pages
cancel-in-progress: false

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Deploy to gh-pages branch
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: .
publish_branch: gh-pages
exclude_assets: '.github,template_repository'
22 changes: 22 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ To send us a pull request, please:
6. Send us a pull request, answering any default questions in the pull request.
7. Pay attention to any automated failures reported in the pull request, and stay involved in the conversation.

## Submit a Blog Post

We welcome community blog contributions for publishing on the GitHub Pages site.

Please follow these requirements:

1. Create your post file in `/blog/posts/` using this filename format: `YYYY-MM-DD-short-title.md`.
2. Start from `/blog/_template.md` and include all required metadata fields:
- `title`
- `author`
- `date` (YYYY-MM-DD)
- `tags` (list)
- `summary`
3. Keep content original, respectful, and relevant to DevOps, DevSecOps, platform engineering, cloud, automation, SRE, or adjacent community learning topics.
4. Add local images under a suitable folder in the repository and use relative links.
5. Open a pull request with the **Blog Post Submission** template and complete every checklist item.

Review expectations:

- Blog pull requests require maintainer review.
- Posts may be edited or declined if they do not meet topic, originality, quality, or community standards.

GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).

Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ The project is not a sponsored operation by any vendors and everything is access

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/N4N33YRCS)

[![Discord Invite Link](https://dcbadge.vercel.app/api/server/vqwPrNQsyK)](https://discord.gg/vqwPrNQsyK)

![GitHub Repo Stars](https://img.shields.io/github/stars/michaelcade/90daysofdevops?style=social?)


Expand Down
2 changes: 2 additions & 0 deletions _sidebar.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
- 90DaysOfDevOps
- [2022 Version](2022.md)
- [2023 Version](2023.md)
- [2024 Version](2024.md)
- [Community Blog](blog/README.md)

- Info
- [Resources](Resources.md)
Expand Down
16 changes: 16 additions & 0 deletions blog/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Community Blog

Welcome to the 90DaysOfDevOps community blog.

This section is for community-submitted posts merged through pull requests.

## Blog Posts

- [Welcome to the Community Blog](/blog/posts/2026-06-24-community-welcome.md)

## Submit a Blog Post

1. Copy the template from [`blog/_template.md`](./_template.md).
2. Create a new file in `blog/posts/` using `YYYY-MM-DD-short-title.md`.
3. Open a pull request using the **Blog Post Submission** template.

13 changes: 13 additions & 0 deletions blog/_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: "Your Post Title"
author: "Your Name"
date: "YYYY-MM-DD"
tags:
- devops
summary: "One or two sentence summary of your post."
---

# Your Post Title

Write your post here.

16 changes: 16 additions & 0 deletions blog/posts/2026-06-24-community-welcome.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: "Welcome to the 90DaysOfDevOps Community Blog"
author: "90DaysOfDevOps Maintainers"
date: "2026-06-24"
tags:
- community
- devops
summary: "An introduction to community blog submissions in this repository."
---

# Welcome to the 90DaysOfDevOps Community Blog

This new blog section allows community members to submit practical DevOps write-ups through pull requests.

Use the template in `blog/_template.md`, add your post to `blog/posts/`, and open a pull request for review.

2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<meta name="description"
content="A learning resource for the community to pick up a foundational theory and hands-on knowledge and understanding of the key areas of DevOps. Follow along and join the community!">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/themes/dark.css" />
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/themes/vue.css" />
</head>

<body>
Expand Down
Loading