Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[add] HTTP proxy & error alert #52

Merged
merged 1 commit into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions .github/workflows/deploy-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ on:
- v*
env:
ARTIFACT_PATH: /tmp/artifact.tar
BOX_NAME: next-bootstrap-ts
BOX_URL: idea2app/next-bootstrap-ts
BOX_NAME: ${{ github.event.repository.name }}
BOX_URL: ${{ github.repository }}

jobs:
deploy_docker_image:
Expand All @@ -20,18 +20,20 @@ jobs:
packages: write
contents: read
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Inject Environment variables
run: |
echo "BOX_NAME=${BOX_NAME@L}" >> "${GITHUB_ENV}"
echo "BOX_URL=${BOX_URL@L}" >> "${GITHUB_ENV}"
cat > .env.local <<EOF
${{ secrets.ENV_FILE }}
EOF
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3

- name: Build Image
uses: docker/build-push-action@v3
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64
Expand All @@ -44,13 +46,14 @@ jobs:
mv ${{ env.ARTIFACT_PATH }} ./docker-compose.yml ./start.sh ./build

- name: Transport Image
uses: garygrossgarten/github-action-scp@release
uses: appleboy/scp-action@v0.1.7
with:
local: ./build
remote: /tmp
source: ./build/*.*
target: /tmp/${{ env.BOX_NAME }}
host: ${{ secrets.HOST }}
username: ${{ secrets.USER }}
password: ${{ secrets.SSH_KEY }}
strip_components: 1

- name: Run Image
uses: garygrossgarten/github-action-ssh@release
Expand All @@ -59,6 +62,9 @@ jobs:
username: ${{ secrets.USER }}
password: ${{ secrets.SSH_KEY }}
command: |
mv /tmp/docker-compose.yml /tmp/start.sh ~/
chmod +x ~/start.sh
echo '${{ secrets.SSH_KEY }}' | sudo -S ~/start.sh ${{ env.ARTIFACT_PATH }}
mkdir -p ~/${{ env.BOX_NAME }}
cd /tmp/${{ env.BOX_NAME }}
mv docker-compose.yml start.sh ~/${{ env.BOX_NAME }}
cd ~/${{ env.BOX_NAME }}
chmod +x start.sh
echo '${{ secrets.SSH_KEY }}' | sudo -S ./start.sh /tmp/${{ env.BOX_NAME }}/${{ env.ARTIFACT_PATH }}
29 changes: 2 additions & 27 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,8 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v3

- uses: pnpm/action-setup@v2
with:
version: 9

- uses: actions/setup-node@v3
if: ${{ !env.VERCEL_TOKEN || !env.VERCEL_ORG_ID || !env.VERCEL_PROJECT_ID }}
with:
node-version: 18
cache: pnpm

- name: Install Dependencies
if: ${{ !env.VERCEL_TOKEN || !env.VERCEL_ORG_ID || !env.VERCEL_PROJECT_ID }}
run: pnpm i --frozen-lockfile

- name: Export Static pages
if: ${{ !env.VERCEL_TOKEN || !env.VERCEL_ORG_ID || !env.VERCEL_PROJECT_ID }}
run: pnpm export

- name: Deploy to GitHub pages
uses: peaceiris/actions-gh-pages@v3
if: ${{ !env.VERCEL_TOKEN || !env.VERCEL_ORG_ID || !env.VERCEL_PROJECT_ID }}
with:
publish_dir: ./out
personal_token: ${{ secrets.GITHUB_TOKEN }}
force_orphan: true
- uses: actions/checkout@v4
if: ${{ env.VERCEL_TOKEN && env.VERCEL_ORG_ID && env.VERCEL_PROJECT_ID }}

- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
if: ${{ env.VERCEL_TOKEN && env.VERCEL_ORG_ID && env.VERCEL_PROJECT_ID }}

- name: Deploy to Vercel
Expand Down
41 changes: 23 additions & 18 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
FROM node:18-slim
FROM node:20-slim AS base
RUN apt-get update && \
apt-get install ca-certificates curl libjemalloc-dev -y --no-install-recommends && \
rm -rf /var/lib/apt/lists/*
# set environment variable to preload JEMalloc
ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
# set GC time, set arenas number, set background_thread run GC
ENV MALLOC_CONF=dirty_decay_ms:1000,narenas:2,background_thread:true
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app

USER root

RUN npm rm yarn -g
RUN npm i pnpm -g

RUN mkdir /home/node/app
WORKDIR /home/node/app

COPY package.json pnpm-lock.yaml /home/node/app/
RUN pnpm i --frozen-lockfile

COPY . /home/node/app
RUN pnpm build

RUN pnpm prune --prod || true \
pnpm store prune
FROM base AS build
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm i --frozen-lockfile
RUN CI=true pnpm build

FROM base
COPY --from=build /app/public ./public
COPY --from=build /app/.next/static ./.next/static
COPY --from=build /app/.next/standalone ./
EXPOSE 3000
CMD ["npm", "start"]
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"
CMD ["node", "server.js"]
22 changes: 7 additions & 15 deletions models/Repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ const GithubToken = process.env.GITHUB_TOKEN;
if (!isServer()) githubClient.baseURI = `${API_Host}/api/GitHub/`;

githubClient.use(({ request }, next) => {
console.log(request.path);

if (GithubToken)
request.headers = {
authorization: `Bearer ${GithubToken}`,
Expand All @@ -30,21 +28,11 @@ export class RepositoryModel extends Stream<GitRepository, RepositoryFilter>(
) {
constructor(public owner = MainOrganization) {
super(owner);
// remove next line on Node.js `require('esm')` fully supported & MobX-RESTful 1.x installed
this.baseURI = owner ? `orgs/${owner}/repos` : 'user/repos';
}

async *openStream(filter: RepositoryFilter) {
const { owner: organization } = this;

if (organization === MainOrganization) {
// @ts-ignore
yield await this.getOne('freeCodeCamp/chinese', filter.relation);

this.totalCount = 1;
} else this.totalCount = 0;

const { loadPage } = GitRepoModel.prototype;
const { loadPage } = GitRepoModel.prototype,
hasAdditional = this.owner === MainOrganization;

for (let i = 1; ; i++) {
const { pageData, totalCount } = await loadPage.call(
Expand All @@ -55,11 +43,15 @@ export class RepositoryModel extends Stream<GitRepository, RepositoryFilter>(
);
if (!pageData[0]) break;

if (i === 1) this.totalCount += totalCount;
this.totalCount = totalCount + (hasAdditional ? 1 : 0);
yield* pageData;

if (pageData.length < this.pageSize) break;
}

if (hasAdditional)
// @ts-ignore
yield await this.getOne('freeCodeCamp/chinese', filter.relation);
}
}

Expand Down
15 changes: 0 additions & 15 deletions next.config.js

This file was deleted.

13 changes: 13 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import setPWA from 'next-pwa';
// @ts-ignore
import withLess from 'next-with-less';

const { NODE_ENV, CI } = process.env,
withPWA = setPWA({
dest: 'public',
register: true,
skipWaiting: true,
disable: NODE_ENV === 'development',
});

export default withLess(withPWA({ output: CI ? 'standalone' : undefined }));
49 changes: 27 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,61 @@
"node": ">=18"
},
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-brands-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-brands-svg-icons": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/react-fontawesome": "^0.2.2",
"@giscus/react": "^3.0.0",
"idea-react": "^2.0.0-rc.2",
"koajax": "^1.1.2",
"koajax": "^3.0.1",
"less": "^4.2.0",
"less-loader": "^12.2.0",
"lodash": "^4.17.21",
"marked": "^13.0.2",
"mobx": "^6.13.0",
"mobx-github": "^0.3.2",
"marked": "^14.1.1",
"mobx": "^6.13.1",
"mobx-github": "^0.3.4",
"mobx-i18n": "^0.5.0",
"mobx-react": "^9.1.1",
"mobx-restful": "^0.7.0-rc.0",
"mobx-restful-table": "^2.0.0-rc.1",
"next": "^14.2.5",
"mobx-restful": "^1.0.1",
"mobx-restful-table": "^2.0.0",
"next": "^14.2.7",
"next-pwa": "~5.6.0",
"next-ssr-middleware": "^0.8.2",
"next-ssr-middleware": "^0.8.7",
"next-with-less": "^3.0.1",
"react": "^18.3.1",
"react-bootstrap": "^2.10.4",
"react-dom": "^18.3.1",
"undici": "^6.19.8",
"web-utility": "^4.4.0"
},
"devDependencies": {
"@babel/plugin-proposal-decorators": "^7.24.7",
"@babel/plugin-transform-typescript": "^7.24.8",
"@babel/plugin-transform-typescript": "^7.25.2",
"@babel/preset-react": "^7.24.7",
"@types/lodash": "^4.17.6",
"@types/node": "^18.19.39",
"@types/react": "^18.3.3",
"@types/lodash": "^4.17.7",
"@types/next-pwa": "^5.6.9",
"@types/node": "^20.16.4",
"@types/react": "^18.3.5",
"eslint": "^8.57.0",
"eslint-config-next": "^14.2.5",
"eslint-config-next": "^14.2.7",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"husky": "^9.0.11",
"lint-staged": "^15.2.7",
"husky": "^9.1.5",
"lint-staged": "^15.2.10",
"prettier": "^3.3.3",
"typescript": "~5.5.3"
"typescript": "~5.5.4"
},
"resolutions": {
"native-file-system-adapter": "npm:@tech_query/native-file-system-adapter@^3.0.1"
},
"prettier": {
"singleQuote": true,
"trailingComma": "all",
"arrowParens": "avoid"
},
"lint-staged": {
"*.{html,md,less,json,yml,js,ts,tsx}": "prettier --write",
"*.{js,jsx,ts,tsx}": "eslint --fix"
"*.{html,md,less,json,yml,js,mjs,ts,tsx}": "prettier --write",
"*.{js,mjs,ts,tsx}": "eslint --fix"
},
"scripts": {
"prepare": "husky install",
Expand All @@ -65,7 +70,7 @@
"export": "next build && next export",
"start": "next start",
"lint": "next lint",
"test": "lint-staged && npm run lint",
"test": "lint-staged && npm run lint && tsc --noEmit",
"pack-image": "docker build -t next-bootstrap-ts:latest .",
"container": "docker rm -f next-bootstrap-ts && docker run --name next-bootstrap-ts -p 3000:3000 -d next-bootstrap-ts:latest"
}
Expand Down
10 changes: 10 additions & 0 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { HTTPError } from 'koajax';
import { configure } from 'mobx';
import { enableStaticRendering, observer } from 'mobx-react';
import type { AppProps } from 'next/app';
Expand All @@ -15,6 +16,15 @@ enableStaticRendering(isServer());

const { t } = i18n;

globalThis.addEventListener?.('unhandledrejection', ({ reason }) => {
var { message, response } = reason as HTTPError;
const { statusText, body } = response || {};

message = body?.message || statusText || message;

if (message) alert(message);
});

const AppShell = observer(({ Component, pageProps }: AppProps) => (
<>
<Head>
Expand Down
8 changes: 7 additions & 1 deletion pages/api/core.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { HTTPError } from 'koajax';
import { NextApiRequest, NextApiResponse } from 'next';
import { ProxyAgent, setGlobalDispatcher } from 'undici';

const { HTTP_PROXY } = process.env;

if (HTTP_PROXY) setGlobalDispatcher(new ProxyAgent(HTTP_PROXY));

export type NextAPI = (
req: NextApiRequest,
Expand All @@ -17,7 +22,8 @@ export function safeAPI(handler: NextAPI): NextAPI {
res.status(400);
return res.send({ message: (error as Error).message });
}
let { message, status, body } = error;
const { message, response } = error;
let { status, body } = response;

res.status(status);
res.statusMessage = message;
Expand Down
6 changes: 5 additions & 1 deletion pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { GitRepository } from 'mobx-github';
import { observer } from 'mobx-react';
import { InferGetServerSidePropsType } from 'next';
import { cache, compose, errorLogger } from 'next-ssr-middleware';
Expand All @@ -23,7 +24,10 @@ export const getServerSideProps = compose(cache(), errorLogger, async () => {
({ archived }) => !archived,
);
return {
props: { cities, repositories },
props: {
cities,
repositories: JSON.parse(JSON.stringify(repositories)) as GitRepository[],
},
};
});

Expand Down
Loading