aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/FUNDING.yml1
-rw-r--r--.github/dependabot.yml6
-rw-r--r--.github/workflows/codeql.yml46
-rw-r--r--.github/workflows/deploy.yml59
-rw-r--r--.github/workflows/docker-build.yml47
-rw-r--r--.github/workflows/ruff.yml42
-rw-r--r--.gitlab-ci.yml34
-rw-r--r--build.py107
8 files changed, 247 insertions, 95 deletions
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..4b822e5
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: [ccleberg]
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..6483b1d
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: "uv"
+ directory: "/"
+ schedule:
+ interval: "weekly"
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..f857dda
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,46 @@
+name: "CodeQL Advanced"
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ analyze:
+ name: Analyze (${{ matrix.language }})
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
+ permissions:
+ security-events: write
+ packages: read
+ actions: read
+ contents: read
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - language: python
+ build-mode: none
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v4
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
+ - if: matrix.build-mode == 'manual'
+ shell: bash
+ run: |
+ echo 'If you are using a "manual" build mode for one or more of the' \
+ 'languages you are analyzing, replace this with the commands to build' \
+ 'your code, for example:'
+ echo ' make bootstrap'
+ echo ' make release'
+ exit 1
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v4
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
new file mode 100644
index 0000000..85eeff7
--- /dev/null
+++ b/.github/workflows/deploy.yml
@@ -0,0 +1,59 @@
+name: Build and Deploy
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build-job:
+ runs-on: ubuntu-latest
+ container:
+ image: ghcr.io/ccleberg/cleberg.net:github-actions
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Run Build
+ run: |
+ echo "Environment is ready. Running build..."
+ echo "r" | ENV=prod uv run build.py
+
+ - name: Upload Build Artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: build-output
+ path: ${{ github.workspace }}/.build/
+ include-hidden-files: true
+
+ deploy-job:
+ runs-on: ubuntu-latest
+ needs: build-job
+ environment: production
+ container:
+ image: ghcr.io/ccleberg/cleberg.net:github-actions
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Download Build Artifacts
+ uses: actions/download-artifact@v4
+ with:
+ name: build-output
+ path: ${{ github.workspace }}/.build/
+
+ - name: Setup SSH and Deploy
+ env:
+ SERVER_IP: ${{ secrets.SERVER_IP }}
+ SERVER_USER: ${{ secrets.SERVER_USER }}
+ SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
+ run: |
+ eval $(ssh-agent -s)
+ echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
+ rsync -avz --delete \
+ -e "ssh -p 2169 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" \
+ .build/ \
+ $SERVER_USER@$SERVER_IP:/var/www/cleberg.net/ \ No newline at end of file
diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml
new file mode 100644
index 0000000..6172cc4
--- /dev/null
+++ b/.github/workflows/docker-build.yml
@@ -0,0 +1,47 @@
+name: Build and Push Docker Image
+
+on:
+ push:
+ branches: [ "main" ]
+ paths:
+ - 'Dockerfile'
+ - 'requirements.txt'
+ - '.github/workflows/docker-build.yml'
+ pull_request:
+ branches: [ "main" ]
+ paths:
+ - 'Dockerfile'
+ - 'requirements.txt'
+ - '.github/workflows/docker-build.yml'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Log in to GHCR
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ghcr.io/${{ github.repository }}
+
+ - name: Build and push
+ uses: docker/build-push-action@v5
+ with:
+ context: .
+ push: true
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml
new file mode 100644
index 0000000..1c0fbea
--- /dev/null
+++ b/.github/workflows/ruff.yml
@@ -0,0 +1,42 @@
+name: Ruff
+
+on:
+ push:
+ branches: [ "main" ]
+ paths:
+ - '**.py'
+ pull_request:
+ branches: [ "main" ]
+ paths:
+ - '**.py'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version: ["3.x"]
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v5
+ with:
+ python-version: ${{ matrix.python-version }}
+ ref: ${{ github.event.pull_request.head.ref }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install pandas dash plotly.express
+ - name: Install Ruff
+ uses: astral-sh/[email protected]
+ - name: Ruff Actions
+ run: |
+ ruff check --fix
+ ruff format
+ - name: Add and Commit
+ uses: EndBug/add-and-commit@v9
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ default_author: github_actions
+ pathspec_error_handling: ignore
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index e6a1137..0000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,34 +0,0 @@
-image: registry.gitlab.com/ccleberg/cleberg-net:latest
-
-stages:
- - build
- - deploy
-
-build-job:
- stage: build
- script:
- - echo "Environment is ready. Running build..."
- - ENV=prod SKIP_DEPLOY=true uv run build.py <<< "r"
- artifacts:
- paths:
- - .build/
-
-deploy-job:
- stage: deploy
- environment: production
- dependencies:
- - build-job
- script:
- - mkdir -p $HOME/.ssh
- - |
- echo "Host homelab-remote
- HostName $SERVER_IP
- User $SERVER_USER
- Port 2169
- StrictHostKeyChecking no
- UserKnownHostsFile /dev/null" > $HOME/.ssh/config
- - chmod 600 $HOME/.ssh/config
- - eval $(ssh-agent -s)
- - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- - echo "Deploying via Python script..."
- - ENV=prod uv run build.py <<< "r"
diff --git a/build.py b/build.py
index 7b19123..44b77d0 100644
--- a/build.py
+++ b/build.py
@@ -86,9 +86,7 @@ def update_index_html(html_snippet, template_path="./.build/index.html"):
end_line_start = end_index
# Construct the new content
- new_content = (
- content[:insert_start] + indented_snippet + content[end_line_start:]
- )
+ new_content = content[:insert_start] + indented_snippet + content[end_line_start:]
# Write back to index.html
with open(template_path, "w", encoding="utf-8") as f:
@@ -190,9 +188,7 @@ def get_recent_posts_html(content_dir="./content/blog", num_posts=3):
lines.append(
f'\t\t<time datetime="{post["date_str"]}">{post["date_full"]}</time>'
)
- lines.append(
- f'\t\t\t<a href="/blog/{post["slug"]}.html">{post["title"]}</a>'
- )
+ lines.append(f'\t\t\t<a href="/blog/{post["slug"]}.html">{post["title"]}</a>')
lines.append("\t</div>")
return "\n".join(lines)
@@ -267,7 +263,9 @@ def run_emacs_publish(dev_mode=True):
if annoying_file.exists():
os.remove(annoying_file)
else:
- print("Warning: .build/cleberg-net.html not found, but Emacs exited successfully.")
+ print(
+ "Warning: .build/cleberg-net.html not found, but Emacs exited successfully."
+ )
def generate_sitemap(build_dir=".build", base_url="https://cleberg.net"):
@@ -290,9 +288,9 @@ def generate_sitemap(build_dir=".build", base_url="https://cleberg.net"):
loc = f"{base_url}{url_path}"
# Last modified time
- lastmod = datetime.fromtimestamp(
- os.path.getmtime(full_path)
- ).strftime("%Y-%m-%d")
+ lastmod = datetime.fromtimestamp(os.path.getmtime(full_path)).strftime(
+ "%Y-%m-%d"
+ )
sitemap_entries.append(f""" <url>
<loc>{loc}</loc>
@@ -308,9 +306,7 @@ def generate_sitemap(build_dir=".build", base_url="https://cleberg.net"):
sitemap_path = os.path.join(build_dir, "sitemap.xml")
with open(sitemap_path, "w", encoding="utf-8") as f:
f.write(sitemap_xml)
- print(
- f"Sitemap generated at {sitemap_path} with {len(sitemap_entries)} entries."
- )
+ print(f"Sitemap generated at {sitemap_path} with {len(sitemap_entries)} entries.")
def deploy_to_server(build_dir, server):
@@ -333,9 +329,7 @@ def start_dev_server(build_dir):
os.chdir(build_dir)
# This will run until interrupted (Ctrl+C)
try:
- subprocess.run(
- [sys.executable, "-m", "http.server", "8000"], check=True
- )
+ subprocess.run([sys.executable, "-m", "http.server", "8000"], check=True)
except KeyboardInterrupt:
print("\nDevelopment server stopped.")
except subprocess.CalledProcessError as e:
@@ -352,66 +346,57 @@ def main():
css_min = theme_dir / "styles.min.css"
env = os.environ.get("ENV", "").casefold()
- skip_deploy = os.environ.get("SKIP_DEPLOY", "").casefold() == "true"
-
- if env == "prod":
- print("Environment: Production")
- method = prompt("Publishing on remote or LAN? [r|l] ").lower()
- if method == "r":
- homelab_server = "homelab-remote"
- elif method == "l":
- homelab_server = "homelab"
- else:
- print("Invalid input. Assuming LAN (homelab)")
- homelab_server = "homelab"
+ deploy = os.environ.get("DEPLOY", "").casefold() == "true"
- # Remove previous build
- remove_build_directory(build_dir)
+ if deploy:
+ print("Deploying to production...")
+ deploy_to_server(build_dir, "homelab-remote")
+ return
+ else:
+ if env == "prod":
+ print("Environment: Production")
- # Minify CSS
- minify_css(css_src, css_min)
+ # Remove previous build
+ remove_build_directory(build_dir)
- # Run publishing script (silenced output)
- run_emacs_publish(dev_mode=False)
+ # Minify CSS
+ minify_css(css_src, css_min)
- # Update index page with latest posts
- update_index_html(html_snippet)
+ # Run publishing script (silenced output)
+ run_emacs_publish(dev_mode=False)
- # Minify index page
- minify_html("./.build/index.html", "./.build/index.html")
+ # Update index page with latest posts
+ update_index_html(html_snippet)
- # Generate sitemap
- generate_sitemap()
+ # Minify index page
+ minify_html("./.build/index.html", "./.build/index.html")
- # Deploy changes
- if not skip_deploy:
- deploy_to_server(build_dir, homelab_server)
- else:
- print("SKIP_DEPLOY is true. Skipping rsync step.")
+ # Generate sitemap
+ generate_sitemap()
- else:
- print("Environment: Development")
+ else:
+ print("Environment: Development")
- # Remove previous build
- remove_build_directory(build_dir)
+ # Remove previous build
+ remove_build_directory(build_dir)
- # Minify CSS
- minify_css(css_src, css_min)
+ # Minify CSS
+ minify_css(css_src, css_min)
- # Run publishing script (with console output)
- run_emacs_publish(dev_mode=True)
+ # Run publishing script (with console output)
+ run_emacs_publish(dev_mode=True)
- # Update index page with latest posts
- update_index_html(html_snippet)
+ # Update index page with latest posts
+ update_index_html(html_snippet)
- # Minify index page
- minify_html("./.build/index.html", "./.build/index.html")
+ # Minify index page
+ minify_html("./.build/index.html", "./.build/index.html")
- # Generate sitemap
- generate_sitemap()
+ # Generate sitemap
+ generate_sitemap()
- # Launch development web server
- start_dev_server(build_dir)
+ # Launch development web server
+ start_dev_server(build_dir)
if __name__ == "__main__":