Fixed RSS date/time
All checks were successful
Docker Deploy / build-and-push (push) Successful in 4m20s
All checks were successful
Docker Deploy / build-and-push (push) Successful in 4m20s
This commit is contained in:
3
.env.example
Normal file
3
.env.example
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# RSS Feed Configuration
|
||||||
|
# Will default to GMT
|
||||||
|
PUBLIC_RSS_TIMEZONE=America/Edmonton
|
||||||
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
@@ -30,6 +30,8 @@ jobs:
|
|||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
push: true
|
push: true
|
||||||
|
build-args: |
|
||||||
|
PUBLIC_RSS_TIMEZONE=${{ vars.PUBLIC_RSS_TIMEZONE }}
|
||||||
tags: |
|
tags: |
|
||||||
${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ github.sha }}
|
${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ github.sha }}
|
||||||
${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
|
${{ secrets.REPO_HOST }}/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
|
||||||
|
|||||||
12
Dockerfile
12
Dockerfile
@@ -46,35 +46,29 @@ RUN --mount=type=cache,id=pnpm,target=/.pnpm-store \
|
|||||||
|
|
||||||
FROM build-deps AS builder
|
FROM build-deps AS builder
|
||||||
|
|
||||||
# Copy source code
|
ARG PUBLIC_RSS_TIMEZONE
|
||||||
|
ENV PUBLIC_RSS_TIMEZONE=${PUBLIC_RSS_TIMEZONE}
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Build the application
|
|
||||||
RUN pnpm run build
|
RUN pnpm run build
|
||||||
|
|
||||||
FROM node:24-alpine AS runtime
|
FROM node:24-alpine AS runtime
|
||||||
|
|
||||||
# Install pnpm for runtime
|
|
||||||
RUN npm install -g pnpm
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy built application
|
|
||||||
COPY --from=builder /app/dist ./dist
|
COPY --from=builder /app/dist ./dist
|
||||||
|
|
||||||
# Copy production dependencies
|
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
|
||||||
# Copy package.json for any runtime needs
|
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
|
|
||||||
# Set environment variables
|
|
||||||
ENV HOST=0.0.0.0 \
|
ENV HOST=0.0.0.0 \
|
||||||
PORT=4321 \
|
PORT=4321 \
|
||||||
NODE_ENV=production
|
NODE_ENV=production
|
||||||
|
|
||||||
# Expose port
|
|
||||||
EXPOSE 4321
|
EXPOSE 4321
|
||||||
|
|
||||||
# Start the application
|
|
||||||
CMD ["node", "./dist/server/entry.mjs"]
|
CMD ["node", "./dist/server/entry.mjs"]
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ services:
|
|||||||
- "${APP_PORT}:4321"
|
- "${APP_PORT}:4321"
|
||||||
environment:
|
environment:
|
||||||
NODE_ENV: production
|
NODE_ENV: production
|
||||||
|
PUBLIC_RSS_TIMEZONE: ${PUBLIC_RSS_TIMEZONE:-}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|||||||
@@ -1,6 +1,38 @@
|
|||||||
import rss from '@astrojs/rss';
|
import rss from '@astrojs/rss';
|
||||||
import { getCollection } from 'astro:content';
|
import { getCollection } from 'astro:content';
|
||||||
|
|
||||||
|
function formatPubDate(date) {
|
||||||
|
const timezone = process.env.PUBLIC_RSS_TIMEZONE
|
||||||
|
? process.env.PUBLIC_RSS_TIMEZONE
|
||||||
|
: import.meta.env.PUBLIC_RSS_TIMEZONE;
|
||||||
|
|
||||||
|
if (!timezone) {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const year = date.getUTCFullYear();
|
||||||
|
const month = String(date.getUTCMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getUTCDate()).padStart(2, '0');
|
||||||
|
|
||||||
|
const formatter = new Intl.DateTimeFormat('en-US', {
|
||||||
|
timeZone: timezone,
|
||||||
|
timeZoneName: 'longOffset',
|
||||||
|
});
|
||||||
|
|
||||||
|
const parts = formatter.formatToParts(date);
|
||||||
|
const offsetPart = parts.find(p => p.type === 'timeZoneName');
|
||||||
|
const offset = offsetPart ? offsetPart.value.replace('GMT', '') : '+00:00';
|
||||||
|
|
||||||
|
const dateStr = `${year}-${month}-${day}T00:00:00${offset}`;
|
||||||
|
|
||||||
|
return new Date(dateStr);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`Invalid timezone "${timezone}":`, e.message);
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function GET(context) {
|
export async function GET(context) {
|
||||||
const posts = await getCollection('posts');
|
const posts = await getCollection('posts');
|
||||||
|
|
||||||
@@ -10,7 +42,7 @@ export async function GET(context) {
|
|||||||
site: context.site,
|
site: context.site,
|
||||||
items: posts.map((post) => ({
|
items: posts.map((post) => ({
|
||||||
title: post.data.title,
|
title: post.data.title,
|
||||||
pubDate: post.data.pubDate,
|
pubDate: formatPubDate(post.data.pubDate),
|
||||||
description: post.data.description || '',
|
description: post.data.description || '',
|
||||||
link: `/post/${post.slug}/`,
|
link: `/post/${post.slug}/`,
|
||||||
})),
|
})),
|
||||||
|
|||||||
Reference in New Issue
Block a user