diff --git a/.github/workflows/build-deploy.yml b/.github/workflows/build-deploy.yml
index dd7b3c346..643969638 100644
--- a/.github/workflows/build-deploy.yml
+++ b/.github/workflows/build-deploy.yml
@@ -4,7 +4,6 @@ on:
workflow_dispatch:
push:
branches:
- - ep2024
- ep2025
jobs:
@@ -15,6 +14,9 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
+ - name: Set timestamp for build/deploy
+ run: echo "TIMESTAMP=$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV
+
- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
@@ -27,28 +29,18 @@ jobs:
cache: "pnpm"
- name: Install dependencies
- run: pnpm install
-
- - name: Set up Python
- uses: actions/setup-python@v5
- with:
- python-version: "3.13"
- cache: "pip"
-
- - name: Install Ansible
- run: pip install ansible
+ run: make install
- name: Build the website
- run: pnpm build
+ run: make build
- name: Set up SSH key
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }}
+ - name: ssh keyscan
+ run: ssh-keyscan "static.europython.eu" > ~/.ssh/known_hosts
+
- name: Deploy to server
- env:
- SSH_USERNAME: ${{ secrets.DEPLOY_SSH_USERNAME }}
- INVENTORY: ${{ secrets.DEPLOY_INVENTORY }}
- run: |
- ansible-playbook -u $SSH_USERNAME -i "$INVENTORY" deploy.yml
+ run: make deploy FORCE_DEPLOY=true
diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
new file mode 100644
index 000000000..8998fa3b1
--- /dev/null
+++ b/.github/workflows/preview.yml
@@ -0,0 +1,102 @@
+name: Preview
+
+on:
+ pull_request:
+
+jobs:
+ preview:
+ name: Run preview
+ runs-on: ubuntu-latest
+ env:
+ PREVIEW_HOSTNAME: ep-preview.click
+ GITHUB_BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set timestamp for build/deploy
+ run: echo "TIMESTAMP=$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV
+
+ - name: Set up pnpm
+ uses: pnpm/action-setup@v4
+ with:
+ run_install: false
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: "pnpm"
+
+ - name: Install dependencies
+ run: make install
+
+ - name: Build the website
+ run: make build
+
+ - name: Set up SSH key
+ uses: webfactory/ssh-agent@v0.9.0
+ with:
+ ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }}
+
+ - name: Get current branch name
+ run: |
+ BRANCH_NAME=$(make safe_branch BRANCH=$GITHUB_BRANCH_NAME)
+ echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITHUB_ENV
+
+ - name: ssh keyscan
+ run: ssh-keyscan "static.europython.eu" > ~/.ssh/known_hosts
+
+ - name: Upload preview
+ run: make preview BRANCH=$GITHUB_BRANCH_NAME
+
+ - name: Update PR Comment
+ uses: actions/github-script@v6
+ if: github.event_name == 'pull_request'
+
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ console.log("Hello world!");
+ const pr_id = ${{ github.event.number }};
+ console.log("PR Id %d", pr_id);
+
+ comments = await github.paginate(github.rest.issues.listComments, {
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: Number(pr_id)
+ })
+
+ const preview_identifier = "# Preview available"
+
+ let comment_id = null;
+ comments.forEach(comment => {
+ if(comment.body.indexOf(preview_identifier) >= 0) {
+ comment_id = comment.id;
+ }
+ });
+
+ const branch_name = process.env.BRANCH_NAME;
+ const url = "https://" + branch_name + "." + process.env.PREVIEW_HOSTNAME;
+ const timestamp = new Date().toISOString();
+ const header = "\n|Key|Value|\n|---|---|\n"
+ const body = preview_identifier + header + "|url|" + url + "|\n|last update|" + timestamp + "|";
+
+ if(comment_id > 0) {
+ await github.rest.issues.updateComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ comment_id: comment_id,
+ body: body
+ });
+
+ } else {
+
+ await github.rest.issues.createComment({
+ issue_number: Number(pr_id),
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: body
+ });
+ }
diff --git a/Makefile b/Makefile
index 9dbdacf03..612dfadee 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,32 @@
+#
+# Variables for remote host
+# =========================
+VPS_USER ?= static_content_user
+VPS_HOST ?= static.europython.eu
+VPS_PROD_PATH ?= /home/static_content_user/content/europython_websites/ep2025
+VPS_PREVIEW_PATH ?= /home/static_content_user/content/previews
+REMOTE_CMD=ssh $(VPS_USER)@$(VPS_HOST)
+
+# Variables for build/deploy
+# ==========================
+export TIMESTAMP ?= $(shell date +%Y%m%d%H%M%S)
+export GIT_VERSION ?= $(shell git rev-parse --short HEAD)
+
+# Variables for deploy
+# ====================
+# Auto-detect and sanitize current git branch
+BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD)
+# Replace "/" and other non-alphanumeric characters with "-"
+SAFE_BRANCH := $(shell echo "$(BRANCH)" | sed 's/[^A-Za-z0-9._-]/-/g')
+FORCE_DEPLOY ?= false
+
+.PHONY: build deploy dev clean install
+
+
+safe_branch:
+ @echo $(SAFE_BRANCH)
+
pre:
- python -m pip install pre-commit ansible
- pre-commit install
npm install -g pnpm
install:
@@ -9,17 +35,36 @@ install:
dev:
pnpm dev
+clean:
+ git clean -fdX
+
+check:
+ pnpm run astro check
+
build:
- pnpm build
+ # TODO: update this to just `pnpm build` after resolving the astro-check warnings
+ pnpm run astro build
+ # NOTE: also let's find a better way to do this :D
+ find ./dist/_astro/ -iname '*.jpg' -delete
-deploy:
- $(if $(findstring Windows_NT, $(OS)), \
- $(error Deployment is not supported on Windows. Use WSL or a Unix-like system.), \
- @read -p "Enter SSH username: " USERNAME; \
- read -p "Enter inline inventory (e.g., 'host1,' (DO NOT forget the trailing comma)): " INVENTORY; \
- ansible-playbook -u $$USERNAME -i "$$INVENTORY" deploy.yml)
+preview: RELEASES_DIR = $(VPS_PREVIEW_PATH)/$(SAFE_BRANCH)/releases
+preview: TARGET = $(RELEASES_DIR)/$(TIMESTAMP)
+preview:
+ echo $(TARGET)
+ @echo "\n\n**** Deploying preview of a branch '$(BRANCH)' (safe: $(SAFE_BRANCH)) to $(TARGET)...\n\n"
+ $(REMOTE_CMD) "mkdir -p $(TARGET)"
+ rsync -avz --delete ./dist/ $(VPS_USER)@$(VPS_HOST):$(TARGET)/
+ $(REMOTE_CMD) "cd $(RELEASES_DIR) && ln -snf $(TIMESTAMP) current"
+ @echo "\n\n**** Preview complete.\n\n"
-clean:
- git clean -fdX
-.PHONY: pre install dev build deploy clean
+ifeq ($(FORCE_DEPLOY), true)
+deploy: RELEASES_DIR = $(VPS_PROD_PATH)/$(SAFE_BRANCH)/releases
+deploy: TARGET = $(RELEASES_DIR)/$(TIMESTAMP)
+deploy:
+ @echo "\n\n**** Deploying branch '$(BRANCH)' (safe: $(SAFE_BRANCH)) to $(TARGET)...\n\n"
+ $(REMOTE_CMD) "mkdir -p $(TARGET)"
+ rsync -avz --delete ./dist/ $(VPS_USER)@$(VPS_HOST):$(TARGET)/
+ $(REMOTE_CMD) "cd $(RELEASES_DIR) && ln -snf $(TIMESTAMP) current"
+ @echo "\n\n**** Deployment complete.\n\n"
+endif
diff --git a/deploy.yml b/deploy.yml
deleted file mode 100644
index 3f33064b1..000000000
--- a/deploy.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-- name: Deploy content to static server
- hosts: all
- vars:
- branch_list:
- - ep2024
- - ep2025
- branch_name:
- "{{ lookup('pipe', 'git rev-parse --abbrev-ref HEAD') | trim }}"
- sanitized_branch_name:
- "{{ branch_name | regex_replace('[^a-zA-Z0-9_-]', '_') }}"
- remote_base_path: "/home/{{ ansible_user }}/content"
-
- tasks:
- - name: Generate UUID for temp directory
- ansible.builtin.set_fact:
- unique_id: "{{ ansible_date_time.iso8601_micro | to_uuid }}"
-
- - name: Define and trim deploy path
- ansible.builtin.set_fact:
- deploy_path: >-
- {{
- (
- remote_base_path + '/europython_websites/' + branch_name
- if branch_name in branch_list else
- remote_base_path + '/previews/' + sanitized_branch_name
- ) | trim
- }}
- temp_dir: "{{ remote_base_path }}/temp/{{ unique_id }}"
-
- - name: Show deployment configuration
- ansible.builtin.debug:
- msg:
- - "Branch Name: '{{ branch_name }}'"
- - "Sanitized Branch Name: '{{ sanitized_branch_name }}'"
- - "Remote Base Path: '{{ remote_base_path }}'"
- - "Deploy Path: '{{ deploy_path }}'"
- - "Temp Dir: '{{ temp_dir }}'"
-
- - name: Ensure the temporary destination directory exists
- ansible.builtin.file:
- path: "{{ temp_dir }}"
- state: directory
- recurse: true
- mode: 750
-
- - name: Synchronize local files to remote temporary directory
- ansible.posix.synchronize:
- src: dist/
- dest: "{{ deploy_path }}/"
- mode: push
- checksum: true
- delete: true
-
- - name: Verify deployment success
- ansible.builtin.find:
- paths: "{{ deploy_path }}"
- recurse: true
- age: -1d
- register: target_dir_check
- failed_when: target_dir_check.matched == 0
-
- - name: Confirm deployment success
- debug:
- msg: "Files successfully deployed to '{{ deploy_path }}/'."
diff --git a/src/components/footer.astro b/src/components/footer.astro
index b0793476b..0d4aad64d 100644
--- a/src/components/footer.astro
+++ b/src/components/footer.astro
@@ -3,6 +3,9 @@ import { Fullbleed } from "./layout/fullbleed";
import links from "../data/links.json";
import { EPSLogo } from "./logo/eps-logo";
+
+const buildTimestamp = import.meta.env.TIMESTAMP;
+const gitVersion = import.meta.env.GIT_VERSION;
---
version: {gitVersion} @ {buildTimestamp}