From 53c32297d2720c8d1a9ccf6ebaf24e3616ba5fb9 Mon Sep 17 00:00:00 2001
From: Elara Liu <40444637+ZL-Asica@users.noreply.github.com>
Date: Thu, 28 Nov 2024 16:46:41 -0600
Subject: [PATCH] feat: add global error handling. (#13)
* ci: update PR labelers.
* feat: add global error handling.
---
.github/workflows/code-lint-format.yml | 4 +
.github/workflows/label-pr-based-on-paths.yml | 91 ++++++++++++++++++
.github/workflows/label-pr-size.yml.yml | 93 +++++++++++++++++++
app.vue | 20 +---
components/layout/SiteHeader.vue | 7 +-
components/pages/EventList.vue | 4 +-
components/pages/SocialLinks.vue | 4 +-
error.vue | 43 +++++++++
i18n/locales/en.json | 15 +++
i18n/locales/zh.json | 15 +++
layouts/default.vue | 14 +++
11 files changed, 287 insertions(+), 23 deletions(-)
create mode 100644 .github/workflows/label-pr-based-on-paths.yml
create mode 100644 .github/workflows/label-pr-size.yml.yml
create mode 100644 error.vue
create mode 100644 layouts/default.vue
diff --git a/.github/workflows/code-lint-format.yml b/.github/workflows/code-lint-format.yml
index b7a4bba..d257c64 100644
--- a/.github/workflows/code-lint-format.yml
+++ b/.github/workflows/code-lint-format.yml
@@ -16,6 +16,10 @@ jobs:
build-and-deploy:
name: 🛠️ Code linter and formatter
runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write
+ issues: write
steps:
- name: 📥 Checkout Code
diff --git a/.github/workflows/label-pr-based-on-paths.yml b/.github/workflows/label-pr-based-on-paths.yml
new file mode 100644
index 0000000..b8ee98c
--- /dev/null
+++ b/.github/workflows/label-pr-based-on-paths.yml
@@ -0,0 +1,91 @@
+name: Auto-label PR based on file paths
+
+on:
+ pull_request:
+ types: [opened, synchronize]
+
+jobs:
+ label:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: write
+ issues: write
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Label PR based on changes with colors
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const prFiles = await github.rest.pulls.listFiles({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: context.issue.number
+ });
+
+ // Define the labels and their colors
+ const labelsToColor = {
+ components: '1f77b4', // Blue - Components Related
+ pages: 'ff7f0e', // Orange - Pages Related
+ stores: '2ca02c', // Green - Stores Related (for Vuex or Pinia)
+ server: '9467bd', // Purple - Server Related
+ layouts: 'ffdd57', // Yellow - Layouts Related
+ assets: 'd62728', // Red - Assets Related
+ i18n: '8c564b', // Brown - i18n Related
+ types: 'e377c2', // Pink - Types Related
+ dependencies: 'e377c2', // Pink - Dependencies Related
+ };
+
+ const labels = new Set();
+
+ const labelPaths = {
+ components: 'components',
+ pages: ['pages', 'app.vue'],
+ stores: ['store', 'stores'],
+ server: 'server',
+ layouts: 'layouts',
+ assets: ['public', 'assets'],
+ i18n: 'i18n',
+ types: 'types',
+ dependencies: ['package.json', 'pnpm-lock.yaml']
+ };
+
+ prFiles.data.forEach(file => {
+ Object.keys(labelPaths).forEach(label => {
+ const paths = Array.isArray(labelPaths[label]) ? labelPaths[label] : [labelPaths[label]];
+ if (paths.some(path => file.filename.startsWith(path))) {
+ labels.add(label);
+ }
+ });
+ });
+
+ if (labels.size > 0) {
+ for (const label of labels) {
+ try {
+ // Check if the label exists
+ await github.rest.issues.getLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ name: label
+ });
+ } catch (error) {
+ // If label doesn't exist, create it with the specified color
+ await github.rest.issues.createLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ name: label,
+ color: labelsToColor[label] || 'b0b0b0', // Use default gray if no color specified
+ });
+ }
+ }
+
+ // Add labels to the PR
+ await github.rest.issues.addLabels({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ labels: Array.from(labels)
+ });
+ }
diff --git a/.github/workflows/label-pr-size.yml.yml b/.github/workflows/label-pr-size.yml.yml
new file mode 100644
index 0000000..521c51f
--- /dev/null
+++ b/.github/workflows/label-pr-size.yml.yml
@@ -0,0 +1,93 @@
+name: size-label
+
+on:
+ pull_request:
+ types: [opened, synchronize]
+
+jobs:
+ size-label:
+ permissions:
+ contents: read
+ pull-requests: write
+ issues: write
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: 🛎️ Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Determine PR size and add label
+ id: size-label
+ uses: pascalgn/size-label-action@v0.5.5
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ IGNORED: |
+ yarn.lock
+ package-lock.json
+ pnpm-lock.yaml
+ package.json
+ .pnp.*
+ dist/
+ build/
+ .cache/
+ LICENSE
+
+ with:
+ sizes: >
+ {
+ "0": "XS",
+ "50": "S",
+ "150": "M",
+ "500": "L",
+ "1000": "XL",
+ "3000": "XXL"
+ }
+
+ - name: Set label colors
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const labelsToColor = {
+ 'XS': 'd4c5f9', // Light purple
+ 'S': 'c2e0c6', // Light green
+ 'M': 'f9d0c4', // Light red
+ 'L': 'f7c6c7', // Light pink
+ 'XL': 'fef2c0', // Light yellow
+ 'XXL': 'e99695', // Light coral
+ };
+
+ const sizeLabel = ${{ steps.size-label.outputs.sizeLabel }};
+ const color = labelsToColor[sizeLabel] || 'b0b0b0';
+
+ if (sizeLabel) {
+ try {
+ await github.rest.issues.updateLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ name: sizeLabel,
+ color: color,
+ });
+ } catch (error) {
+ // Label doesn't exist, create it
+ await github.rest.issues.createLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ name: sizeLabel,
+ color: color,
+ });
+ }
+ }
+
+ - name: Comment on large PRs
+ if: ${{ contains('XL XXL', steps.size-label.outputs.sizeLabel) }}
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ body: "This PR is too large and may need to be broken into smaller pieces."
+ });
diff --git a/app.vue b/app.vue
index 890b965..c298060 100644
--- a/app.vue
+++ b/app.vue
@@ -1,24 +1,12 @@
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/i18n/locales/en.json b/i18n/locales/en.json
index 8436ad6..69767b1 100644
--- a/i18n/locales/en.json
+++ b/i18n/locales/en.json
@@ -20,5 +20,20 @@
"language": "Switch language",
"link": "Click to visit %{link}",
"external": "Open in a new tab"
+ },
+ "error": {
+ "backToHome": "Back to home",
+ "unauthorized": {
+ "title": "(¬_¬) Unauthorized",
+ "description": "Sorry, you need to log in or authorize to access this page 🔑"
+ },
+ "notFound": {
+ "title": "(;′⌒`) Page not found",
+ "description": "Sorry, the page you are looking for is missing or never existed 🔍"
+ },
+ "default": {
+ "title": "(╥﹏╥) Server error",
+ "description": "Sorry, something went wrong on our end, we are working on it 🛠️"
+ }
}
}
diff --git a/i18n/locales/zh.json b/i18n/locales/zh.json
index 746bb57..e3afbc1 100644
--- a/i18n/locales/zh.json
+++ b/i18n/locales/zh.json
@@ -20,5 +20,20 @@
"language": "切换语言",
"link": "点击跳转至 %{title}",
"external": "此链接将在新标签页中打开"
+ },
+ "error": {
+ "backToHome": "返回首页",
+ "unauthorized": {
+ "title": "(¬_¬) 未授权",
+ "description": "抱歉,您需要登录或授权才能访问这个页面 🔑"
+ },
+ "notFound": {
+ "title": "(;′⌒`) 页面迷路啦~",
+ "description": "抱歉,您要找的页面已经不见了,或者它从未存在过 🔍"
+ },
+ "default": {
+ "title": "(╥﹏╥) 服务器出错啦~",
+ "description": "抱歉,内部出现了一点问题,我们正在抢修 🛠️"
+ }
}
}
diff --git a/layouts/default.vue b/layouts/default.vue
new file mode 100644
index 0000000..994e03b
--- /dev/null
+++ b/layouts/default.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+