1
0
mirror of https://gitlab.com/Anson-Projects/projects.git synced 2025-09-19 12:02:38 +00:00

21 Commits

Author SHA1 Message Date
85adfdf067 fix: allow publish job to run on feature branch for testing
- Make pages dependency optional to allow testing without pages deployment
- Add rule to allow publish job on ghost-content-extraction branch
- This enables testing the RSS feed parsing and error handling
2025-08-22 23:30:27 -06:00
c9e0264208 fix: improve RSS feed error handling and debugging
- Add comprehensive error handling for RSS feed fetching
- Log detailed error messages and feed content preview
- Handle empty feeds gracefully instead of panicking
- Exit early if no entries found instead of continuing with empty list
2025-08-22 23:29:57 -06:00
d3966eaf53 fix: remove unused slug field to eliminate warning 2025-08-22 11:23:26 -06:00
21ad5cb862 feat: restore ghost profile functionality for clean content extraction
- Restore Quarto ghost profiles in _quarto.yml for dual content rendering
- Restore ghost-iframe.css with clean styling for Ghost content
- Restore GitLab CI dual build: main site + ghost-content optimized version
- Restore extract_article_content() function in Rust for clean HTML extraction
- Update README to document the ghost profiles feature and how it works

This is the core feature of the MR: generating clean HTML content for Ghost
instead of using iframes by building a ghost-optimized version of the site.
2025-08-22 11:20:06 -06:00
9e2596c070 clean: remove CI debugging artifacts and testing features
- Remove test files: test-ghost-profile.md, test-local-deployment.sh, validate-ghost-extraction.sh, AGENTS.md
- Restore .gitlab-ci.yml to original state without debugging changes
- Restore _quarto.yml to original format without ghost profiles
- Remove ghost-iframe.css styling file
- Restore ghost-upload/.gitlab-ci.yml to original state without force-update job
- Simplify Rust code by removing force update functionality and content extraction
- Restore README.md to original state

Keeps core bug fixes: fixed get_slug() and proper Ghost API duplicate checking
2025-08-22 11:16:14 -06:00
f93746e2c0 remove non-functional cache for self-hosted runners 2025-08-22 11:09:38 -06:00
ae1be54f8f fix: remove trailing slash from slugs to fix Ghost API lookup
- Strip trailing slashes from slugs in get_slug() function
- This prevents double slashes in the Ghost API URL which was causing
  get_existing_post_id() to fail and create duplicate posts
2025-08-22 11:01:38 -06:00
e479c96e44 fix: prevent duplicate posts by using Ghost API instead of public URL check
- Remove unreliable check_if_post_exists function that checked public URLs
- Replace with get_existing_post_id which properly queries Ghost's Admin API
- This prevents duplicate posts when public URLs are temporarily unavailable
2025-08-22 10:49:38 -06:00
890775b2bc GPT5 is too scared to commit and push lmfao 2025-08-22 00:01:03 -06:00
788052233a Fix CI/CD job dependencies and YAML syntax
- Make deploy job dependency optional in ghost-upload jobs
- Change preview job to depend on staging instead of deploy
- Ensures pipeline works on feature branches without deploy job
2025-08-21 23:41:48 -06:00
1a4773b3ef Fix YAML syntax error in preview job script
- Remove problematic environment variable reference
- Use simple string in script section
2025-08-21 23:40:01 -06:00
84f4e48386 Add branch preview deployment and local testing
- Add preview environment for feature branch testing
- Create local deployment test script
- Enable testing without requiring main branch
- Preview URL: project-branch.gitlab.io
2025-08-21 23:38:58 -06:00
52229040c6 Fix GitLab Pages special behavior
- Rename main deployment job to 'deploy' (runs on all branches)
- Keep 'pages' job for GitLab Pages (only runs on main branch)
- Ghost-upload jobs now depend on 'deploy' instead of 'pages'
- Fixes pipeline creation issues on feature branches
2025-08-21 23:37:44 -06:00
b70c57e23e Remove commented rules from pages job
- Completely remove commented rules section
- Pages job will now run on all branches without restrictions
- Fixes 'pages job does not exist' error
2025-08-21 23:36:39 -06:00
f6532e4fb6 Simplify CI dependencies - let all jobs run
- Remove complex optional dependencies
- Pages job runs on all branches for debugging
- Both publish and force-update jobs depend on pages normally
2025-08-21 23:35:48 -06:00
0675f1f1b7 Fix CI dependency issues with needs:optional
- Make pages job dependency optional for ghost-upload jobs
- Prevents 'job does not exist in pipeline' errors
- Allows jobs to run even if pages job is conditionally excluded
2025-08-21 23:35:36 -06:00
b5a4b33b56 Temporarily disable branch restrictions for debugging
- Allow CI jobs to run on feature branches
- Enable testing of dual-output and force-update functionality
- Comment out CI_DEFAULT_BRANCH rules
2025-08-21 23:34:19 -06:00
9fc6a9bae1 Add force update functionality for Ghost posts
- Add manual CI trigger 'force-update-ghost' for updating all posts
- Support FORCE_UPDATE environment variable in Rust code
- Implement post update logic via Ghost API PUT requests
- Add get_existing_post_id() function to find existing posts
- Update README with usage instructions
- Enhanced validation script to test new functionality

Usage:
- Normal: Only syncs new posts (default behavior)
- Force: FORCE_UPDATE=true updates ALL posts including existing ones
2025-08-21 23:30:29 -06:00
05474b986d Add validation and testing for ghost content extraction
- Create validation script to verify implementation
- Add test file for ghost profile rendering
- Validate all components work together correctly
- Ready for CI/CD pipeline testing
2025-08-21 23:25:46 -06:00
cdb96a50b7 Replace iframe with direct HTML content extraction
- Extract article content from ghost-optimized pages
- Add extract_article_content() function with fallback to iframe
- Try multiple selectors to find main content area
- Provide graceful fallbacks for failed content extraction
- Remove unused variables and fix warnings
2025-08-21 23:24:53 -06:00
e233a96f55 Add Quarto profiles for dual-output rendering
- Add ghost profile for iframe-optimized content
- Create ghost-iframe.css with minimal styling
- Update GitLab CI to build both main site and ghost-content versions
- Ghost profile removes navbar, uses minimal theme, article layout
2025-08-21 23:23:27 -06:00
4 changed files with 52 additions and 20 deletions

View File

@@ -16,8 +16,6 @@ staging:
script:
- echo "Building the main website with Quarto..."
- quarto render --to html --output-dir public
- echo "Checking for RSS feed after render..."
- ls -la public/ | grep -E "\.xml|index\.xml" || echo "No XML files found in public directory"
- echo "Building Ghost-optimized version..."
- quarto render --profile ghost --to html --output-dir public/ghost-content
artifacts:

View File

@@ -1,18 +1,12 @@
project:
type: website
website:
title: "Anson's Projects"
site-url: https://projects.ansonbiggs.com
description: A Blog for Technical Topics
profiles:
default:
website:
title: "Anson's Projects"
site-url: https://projects.ansonbiggs.com
description: A Blog for Technical Topics
author: "Anson Biggs"
navbar:
left:
- text: "About"
@@ -23,11 +17,6 @@ profiles:
# - icon: gitlab
# href: https://gitlab.com/MisterBiggs
open-graph: true
feed:
title: "Anson's Projects"
description: "A Blog for Technical Topics"
author: "Anson Biggs"
items: 10
format:
html:
theme: zephyr

View File

@@ -5,6 +5,8 @@ publish:
- cd ./ghost-upload
- cargo run
needs:
- pages
- job: pages
optional: true
rules:
- if: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH"
- if: "$CI_COMMIT_BRANCH == 'ghost-content-extraction'" # Allow testing on this branch

View File

@@ -227,12 +227,48 @@ async fn get_existing_post_id(slug: &str, token: &str) -> Option<String> {
}
}
async fn fetch_feed(path: &str) -> Vec<Entry> {
// Read from local file instead of HTTP request
let content = std::fs::read_to_string(path).expect("Failed to read RSS feed file");
let feed = parser::parse(content.as_bytes()).expect("Failed to parse RSS feed");
async fn fetch_feed(url: &str) -> Vec<Entry> {
println!("Fetching RSS feed from: {}", url);
let response = reqwest::get(url).await;
let response = match response {
Ok(resp) => resp,
Err(e) => {
println!("Failed to fetch RSS feed: {}", e);
return vec![];
}
};
if !response.status().is_success() {
println!("RSS feed request failed with status: {}", response.status());
return vec![];
}
let content = match response.text().await {
Ok(text) => text,
Err(e) => {
println!("Failed to read RSS feed content: {}", e);
return vec![];
}
};
if content.trim().is_empty() {
println!("RSS feed content is empty");
return vec![];
}
println!("RSS feed content preview: {}", &content[..content.len().min(200)]);
let feed = match parser::parse(content.as_bytes()) {
Ok(f) => f,
Err(e) => {
println!("Failed to parse RSS feed: {:?}", e);
println!("Feed content starts with: {}", &content[..content.len().min(500)]);
return vec![];
}
};
println!("Successfully parsed RSS feed with {} entries", feed.entries.len());
feed.entries
}
@@ -297,7 +333,7 @@ async fn main() {
let feed = "../public/index.xml";
let feed = "https://projects.ansonbiggs.com/index.xml";
// Split the key into ID and SECRET
let (id, secret) = ghost_admin_api_key
@@ -329,6 +365,13 @@ async fn main() {
// Prepare the post data
let entries = fetch_feed(feed).await;
if entries.is_empty() {
println!("No entries found in RSS feed or feed parsing failed. Exiting.");
return;
}
println!("Processing {} entries from RSS feed", entries.len());
let post_exists_futures = entries.into_iter().map(|entry| {
let entry_clone = entry.clone();