mirror of
https://github.com/ipfs/ipfs-blog.git
synced 2026-07-06 01:41:43 +02:00
feat: exclude scheduled posts and links
feat: automatically deploy scheduled posts or links
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
name: Check for scheduled posts to publish
|
||||
on:
|
||||
schedule:
|
||||
- cron: '* 9,21 * * *'
|
||||
jobs:
|
||||
check-n-publish:
|
||||
name: Check for scheduled posts and publish if any found
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Check for scheduled posts
|
||||
run: echo "::set-output name=should_publish::$(${{ github.workspace }}/scripts/scheduled-publishing.js)"
|
||||
id: should_publish_step
|
||||
- name: Trigger Fleek Build
|
||||
if: ${{ steps.should_publish_step.outputs.should_publish == 'true' }}
|
||||
id: deploy
|
||||
uses: fleekhq/action-deploy@v1
|
||||
with:
|
||||
apiKey: ${{ secrets.FLEEK_API_KEY }}
|
||||
- name: Scheduled posts published
|
||||
if: ${{ steps.should_publish_step.outputs.should_publish == 'true' }}
|
||||
run: echo "Check https://blog.ipfs.io"
|
||||
|
||||
Generated
+2
@@ -33,6 +33,7 @@
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-vue": "^7.9.0",
|
||||
"gray-matter": "^4.0.2",
|
||||
"husky": "^6.0.0",
|
||||
"lint-staged": "^10.5.4",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -41,6 +42,7 @@
|
||||
"markdown-it-task-lists": "^2.1.1",
|
||||
"markdown-it-video": "^0.6.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"p-map": "^4.0.0",
|
||||
"postcss": "^7.0.35",
|
||||
"prettier": "^2.2.1",
|
||||
"slug": "^4.0.3",
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-vue": "^7.9.0",
|
||||
"gray-matter": "^4.0.2",
|
||||
"husky": "^6.0.0",
|
||||
"lint-staged": "^10.5.4",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -38,6 +39,7 @@
|
||||
"markdown-it-task-lists": "^2.1.1",
|
||||
"markdown-it-video": "^0.6.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"p-map": "^4.0.0",
|
||||
"postcss": "^7.0.35",
|
||||
"prettier": "^2.2.1",
|
||||
"slug": "^4.0.3",
|
||||
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Scheduled Publishing of posts and links.
|
||||
* This script checks for any blog posts and links that are scheduled to
|
||||
* be published, but are to be published today. If there is at least
|
||||
* one found, a build is trigged in fleek, updating the website
|
||||
* with the latest data.
|
||||
*/
|
||||
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const pMap = require('p-map')
|
||||
const matter = require('gray-matter')
|
||||
const dayjs = require('dayjs')
|
||||
|
||||
const isBetween = require('dayjs/plugin/isBetween')
|
||||
dayjs.extend(isBetween)
|
||||
|
||||
async function main() {
|
||||
// read files contents concurrently, 10 at a time
|
||||
const contentDir = path.resolve(__dirname, '../src/_blog')
|
||||
const files = await pMap(
|
||||
await fs.promises.readdir(contentDir),
|
||||
(filename) => {
|
||||
if (!filename.endsWith('.md')) {
|
||||
return null
|
||||
}
|
||||
|
||||
return fs.promises.readFile(path.resolve(contentDir, filename), 'utf8')
|
||||
},
|
||||
{ concurrency: 10 }
|
||||
)
|
||||
|
||||
const output = files
|
||||
// exclude possible nulls
|
||||
.filter((result) => !!result)
|
||||
// process files into publishable items (posts or links)
|
||||
.reduce((items, fileContent) => {
|
||||
const metadata = matter(fileContent).data
|
||||
|
||||
if (metadata.type && metadata.data) {
|
||||
// links
|
||||
items.push(...metadata.data)
|
||||
} else {
|
||||
items.push(metadata)
|
||||
}
|
||||
|
||||
return items
|
||||
}, [])
|
||||
// check if there is at least one publish date in the future
|
||||
.some((item) => {
|
||||
let publishDate
|
||||
|
||||
// blog post
|
||||
if (item.permalink) {
|
||||
publishDate = item.date
|
||||
}
|
||||
|
||||
// links
|
||||
if (item.url && item.publish_date) {
|
||||
publishDate = item.publish_date
|
||||
}
|
||||
|
||||
if (!publishDate) {
|
||||
return false
|
||||
}
|
||||
|
||||
// we trim to the hour to avoid counting the initial delays on triggering
|
||||
// the job, which could cause the time calculations to exclude specific
|
||||
// scheduled dates and times.
|
||||
const now = dayjs(new Date()).startOf('hour')
|
||||
const timeMatch = dayjs(new Date(publishDate)).isBetween(
|
||||
now.subtract(12, 'hour'),
|
||||
now
|
||||
)
|
||||
|
||||
// using stderr since stdout is used for GH workflow output
|
||||
if (timeMatch) {
|
||||
console.error(`Found post/link to publish: "${item.title}"`)
|
||||
}
|
||||
|
||||
return timeMatch
|
||||
})
|
||||
|
||||
if (!output) {
|
||||
console.error('Nothing found to publish.')
|
||||
}
|
||||
|
||||
// output true or false: should trigger publish or not
|
||||
// GH Workflow step reads from stdout
|
||||
console.log(output)
|
||||
}
|
||||
|
||||
main()
|
||||
@@ -1,4 +1,32 @@
|
||||
const slug = require('slug')
|
||||
const dayjs = require('dayjs')
|
||||
|
||||
function shouldBeHidden(frontmatter) {
|
||||
const isDateInFuture = (date) => dayjs(new Date(date)).isAfter(dayjs())
|
||||
let shouldHide = frontmatter.hidden || false
|
||||
|
||||
// sitemap config
|
||||
if (frontmatter.sitemap) {
|
||||
shouldHide = shouldHide || frontmatter.sitemap.exclude
|
||||
}
|
||||
|
||||
// scheduled posts
|
||||
// see auto-publishing of scheduled posts here: https://github.com/ipfs/ipfs-blog/issues/147
|
||||
if (
|
||||
!shouldHide &&
|
||||
frontmatter.permalink && // permalink is unique to posts
|
||||
frontmatter.date
|
||||
) {
|
||||
shouldHide = shouldHide || isDateInFuture(frontmatter.date)
|
||||
}
|
||||
|
||||
// scheduled links (path is unique to links)
|
||||
if (!shouldHide && frontmatter.path && frontmatter.publish_date) {
|
||||
shouldHide = shouldHide || isDateInFuture(frontmatter.publish_date)
|
||||
}
|
||||
|
||||
return shouldHide
|
||||
}
|
||||
|
||||
module.exports = (options, context) => ({
|
||||
extendPageData($page) {
|
||||
@@ -18,8 +46,8 @@ module.exports = (options, context) => ({
|
||||
frontmatter.authorKey = authorKey
|
||||
}
|
||||
|
||||
// exclude a page from the feed & robots if excluded from sitemap
|
||||
if (frontmatter.sitemap && frontmatter.sitemap.exclude) {
|
||||
// exclude hidden pages (sitemap config, future publishes, etc)
|
||||
if (shouldBeHidden(frontmatter)) {
|
||||
frontmatter.feed = {
|
||||
enable: false,
|
||||
}
|
||||
@@ -30,6 +58,18 @@ module.exports = (options, context) => ({
|
||||
} else {
|
||||
frontmatter.meta = [noIndex]
|
||||
}
|
||||
|
||||
frontmatter.hidden = true
|
||||
$page.hidden = true
|
||||
}
|
||||
|
||||
// set links has hidden (future publishes, etc)
|
||||
if (frontmatter.data) {
|
||||
frontmatter.data.forEach((item) => {
|
||||
if (shouldBeHidden(item)) {
|
||||
item.hidden = true
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
@@ -128,14 +128,8 @@ export default {
|
||||
return false
|
||||
}
|
||||
|
||||
if (
|
||||
page.frontmatter &&
|
||||
(page.frontmatter.sitemap ? !page.frontmatter.sitemap.exclude : true)
|
||||
) {
|
||||
result.push({
|
||||
...page,
|
||||
category: defaultCategory,
|
||||
})
|
||||
if (page.frontmatter && !page.frontmatter.hidden) {
|
||||
result.push({ ...page, category: defaultCategory })
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Layout v-if="!$frontmatter.type">
|
||||
<Layout v-if="isVisible">
|
||||
<article itemscope itemtype="https://schema.org/BlogPosting">
|
||||
<PostHero
|
||||
:title="$page.title"
|
||||
@@ -46,7 +46,18 @@ export default {
|
||||
data: () => ({
|
||||
showComments: null,
|
||||
}),
|
||||
computed: {
|
||||
// hidden field set in plugins/pageData.js
|
||||
isVisible() {
|
||||
return !this.$root.$page.hidden
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.isVisible) {
|
||||
// path to 404 is relative to support ipfs sub path deployments
|
||||
return this.$router.replace({ path: '../404' })
|
||||
}
|
||||
|
||||
const ipfsPathRegExp = /^(\/(?:ipfs|ipns)\/[^/]+)/
|
||||
const ipfsPathPrefix =
|
||||
(window.location.pathname.match(ipfsPathRegExp) || [])[1] || ''
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const checkItem = ({
|
||||
export function checkItem({
|
||||
postType,
|
||||
tags,
|
||||
title,
|
||||
@@ -7,7 +7,7 @@ export const checkItem = ({
|
||||
searchedText = [],
|
||||
activeCategory = '',
|
||||
activeAuthor = '',
|
||||
}) => {
|
||||
}) {
|
||||
if (activeCategory && decodeURI(activeCategory) !== postType) {
|
||||
return false
|
||||
}
|
||||
@@ -40,13 +40,13 @@ export const checkItem = ({
|
||||
return true
|
||||
}
|
||||
|
||||
export const parseProtectedPost = (
|
||||
export function parseProtectedPost(
|
||||
post,
|
||||
activeTags = [],
|
||||
searchedText = [],
|
||||
activeCategory = '',
|
||||
activeAuthor = ''
|
||||
) => {
|
||||
) {
|
||||
if (!post.frontmatter.data) {
|
||||
return []
|
||||
}
|
||||
@@ -55,6 +55,7 @@ export const parseProtectedPost = (
|
||||
|
||||
post.frontmatter.data.forEach((item) => {
|
||||
if (
|
||||
item.hidden ||
|
||||
!checkItem({
|
||||
postType: post.frontmatter.type,
|
||||
tags: item.tags,
|
||||
|
||||
@@ -6,7 +6,6 @@ sitemap:
|
||||
data:
|
||||
- title: IPFS Community Meetup, April 2021
|
||||
date: 2021-04-27
|
||||
publishing_date:
|
||||
path: https://www.meetup.com/San-Francisco-IPFS/events/276123324/
|
||||
card_image: "/2021-04-15-cardheader-ipfs-meetup-nft-april2021.png"
|
||||
tags:
|
||||
@@ -14,7 +13,6 @@ data:
|
||||
- official meetup
|
||||
- title: Cal Hacks hello:world
|
||||
date: 2021-04-16
|
||||
publishing_date: 2021-04-15 17:06:47 +0000
|
||||
path: https://helloworld.calhacks.io/
|
||||
card_image: "/2021-04-15-cardheader-hello-world.png"
|
||||
tags:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
---
|
||||
publishing_date:
|
||||
title: Welcome to IPFS Weekly 131
|
||||
description: Uniswap Interface hosting on IPFS, a call for Filecoin user testers,
|
||||
and more from around the ecosystem!
|
||||
|
||||
Reference in New Issue
Block a user