diff --git a/.github/gen-page-preview/main.spec.ts b/.github/gen-page-preview/main.spec.ts
index 5f390374..f9ab1c7e 100644
--- a/.github/gen-page-preview/main.spec.ts
+++ b/.github/gen-page-preview/main.spec.ts
@@ -96,7 +96,8 @@ test("page screenshot", async ({ page }) => {
}
const images = screenshot_urls.map(
- (o) => `## ${o.file} \n\n![${o.file}](${o.url})\n`
+ (o) =>
+ `\n${o.file}
\n\n## ${o.file} \n\n![${o.file}](${o.url})\n \n`
);
const comments = await octokit.issues.listComments({
owner: OWNER,
diff --git a/.github/markdown-header-check/markdown-header.ts b/.github/markdown-header-check/markdown-header.ts
index c0a978c8..5b999856 100644
--- a/.github/markdown-header-check/markdown-header.ts
+++ b/.github/markdown-header-check/markdown-header.ts
@@ -1,11 +1,30 @@
import axios from "axios";
+import * as crypto from "crypto";
import * as fs from "fs";
import * as matter from "gray-matter";
import * as path from "path";
import { exit } from "process";
+interface FileDetails {
+ filePath: string;
+ fields: {
+ [key: string]: any;
+ };
+ oldFile: string | null;
+ isChanged: boolean;
+}
+
+function getGrayMatter(content: string): {
+ data: {
+ [key: string]: any;
+ };
+} {
+ // @ts-ignore
+ return matter(content);
+}
+
(async () => {
- const getAllFiles = (searchPath: string) => {
+ function getAllFiles(searchPath: string) {
const files = fs.readdirSync(searchPath);
const results: string[] = [];
@@ -20,17 +39,28 @@ import { exit } from "process";
}
});
return results;
- };
- const getHeaderFields = (filePath: string) => {
+ }
+
+ function getHeaderFields(filePath: string): {
+ [key: string]: any;
+ } {
const content = fs.readFileSync(filePath, "utf8");
- const { data } = matter(content);
+ const { data } = getGrayMatter(content);
return data;
- };
+ }
- const getHTTPContent = async (url: string) => {
- const response = await axios.get(url);
- return response.data;
- };
+ async function getHTTPContent(url: string): Promise {
+ try {
+ const response = await axios.get(url);
+ if (response.status !== 200) {
+ return null;
+ }
+ return response.data;
+ } catch (error) {
+ console.warn(error);
+ return null;
+ }
+ }
const files = getAllFiles(".")
.filter((x) => x.endsWith(".md"))
@@ -42,32 +72,60 @@ import { exit } from "process";
other: ["title", "description", "createdAt", "updatedAt"],
};
- const forBlog = async (
- file: string,
- fields: { [key: string]: any },
+ async function forBlog(
+ fileDetails: FileDetails,
authors: [{ [key: string]: any }],
categories: [{ [key: string]: any }]
- ) => {
+ ) {
+ const file = fileDetails.filePath;
+ const oldFile = fileDetails.oldFile;
+ const fields = fileDetails.fields;
+ const isChanged = fileDetails.isChanged;
+
// 執筆者の確認
const author = fields["author"];
if (authors.findIndex((x) => x.slug === author) === -1) {
- console.log(`${file}: 執筆者が正しくありません (${author})`);
+ console.warn(`${file}: 執筆者が正しくありません (${author})`);
return false;
}
// カテゴリーの確認
const category = fields["category"];
if (categories.findIndex((x) => x.slug === category) === -1) {
- console.log(`${file}: カテゴリが正しくありません (${category})`);
+ console.warn(`${file}: カテゴリが正しくありません (${category})`);
return false;
}
+ if (oldFile !== null && isChanged) {
+ const oldFields = getGrayMatter(oldFile).data;
+ if (oldFields["updatedAt"] == fields["updatedAt"]) {
+ console.warn(
+ `${file}: 更新日時が変更されていません (${fields["updatedAt"]})`
+ );
+ return false;
+ }
+ }
+
return true;
- };
+ }
+
+ async function forOther(fileDetails: FileDetails) {
+ const file = fileDetails.filePath;
+ const oldFile = fileDetails.oldFile;
+ const fields = fileDetails.fields;
+ const isChanged = fileDetails.isChanged;
- const forOther = (file: string, fields: { [key: string]: any }) => {
+ if (oldFile !== null && isChanged) {
+ const oldFields = getGrayMatter(oldFile).data;
+ if (oldFields["updatedAt"].toString() == fields["updatedAt"].toString()) {
+ console.warn(
+ `${file}: 更新日時が変更されていません (${fields["updatedAt"]})`
+ );
+ return false;
+ }
+ }
return true;
- };
+ }
const authors = await getHTTPContent(
"https://raw.githubusercontent.com/jaoafa/jaoweb/master/content/blog/authors.json"
@@ -84,16 +142,33 @@ import { exit } from "process";
const requiredFieldsForFile = requiredFields[fileType];
for (const field of requiredFieldsForFile) {
if (!fields[field]) {
- console.log(`${file}: 必要なフィールド ${field} がありません。`);
+ console.warn(`${file}: 必要なフィールド ${field} がありません。`);
isValid = false;
}
}
+ const oldFile = await getHTTPContent(
+ `https://raw.githubusercontent.com/jaoafa/jaoweb-docs/main/${file.replace(
+ /\\/g,
+ "/"
+ )}`
+ );
+ const content = fs.readFileSync(file, "utf8");
+
+ const fileDetails: FileDetails = {
+ filePath: file,
+ fields: fields,
+ oldFile: oldFile,
+ isChanged:
+ crypto.createHash("sha256").update(oldFile).digest("hex") !=
+ crypto.createHash("sha256").update(content).digest("hex"),
+ };
+
if (fileType == "blog") {
- const vaild = forBlog(file, fields, authors, categories);
+ const vaild = await forBlog(fileDetails, authors, categories);
if (!vaild) isValid = false;
} else {
- const vaild = forOther(file, fields);
+ const vaild = await forOther(fileDetails);
if (!vaild) isValid = false;
}
}
diff --git a/.github/workflows/markdown-header-check.yml b/.github/workflows/markdown-header-check.yml
index c4b90df0..8299121d 100644
--- a/.github/workflows/markdown-header-check.yml
+++ b/.github/workflows/markdown-header-check.yml
@@ -43,7 +43,9 @@ jobs:
- name: Run markdown-header
run: |
- node .github/markdown-header-check/markdown-header.js | tee markdown-header-output.txt
- cat markdown-header-output.txt | reviewdog -efm="%f: %m" -name="markdown-header" -reporter=github-pr-review
+ node .github/markdown-header-check/markdown-header.js 2>&1 | tee markdown-header-output.txt
+ EXITCODE=$?
+ cat markdown-header-output.txt 1>&2 | reviewdog -efm="%f: %m" -name="markdown-header" -reporter=github-pr-review
+ if [ $EXITCODE -ne 0 ]; then exit 1; fi
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}