Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
takonasu committed Mar 15, 2021
0 parents commit baf0d5b
Show file tree
Hide file tree
Showing 24 changed files with 6,609 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
FROM node:14-slim
WORKDIR /workspace
46 changes: 46 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// https://github.com/microsoft/vscode-dev-containers/tree/v0.154.0/containers/docker-existing-docker-compose
// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml.
{
"name": "TwinteTimetableServiceDevContainer",

// Update the 'dockerComposeFile' list if you have more compose files or use different names.
// The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
"dockerComposeFile": [
"docker-compose.yml"
],

// The 'service' property is the name of the service for the container that VS Code should
// use. Update this value and .devcontainer/docker-compose.yml to the real service name.
"service": "node",

// The optional 'workspaceFolder' property is the path VS Code should open by default when
// connected. This is typically a file mount in .devcontainer/docker-compose.yml
"workspaceFolder": "/workspace",

// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": null
},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"zxh404.vscode-proto3"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Uncomment the next line if you want start specific services in your Docker Compose config.
// "runServices": [],

// Uncomment the next line if you want to keep your containers running after VS Code shuts down.
// "shutdownAction": "none",

// Uncomment the next line to run commands after the container is created - for example installing curl.
"postCreateCommand": "apt update && apt install -y git && chmod a+x ./proto-gen.sh",

// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
// "remoteUser": "vscode"
}
46 changes: 46 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
version: '3'
services:
# Update this to the name of the service you want to work with in your docker-compose.yml file
node:
# If you want add a non-root user to your Dockerfile, you can use the "remoteUser"
# property in devcontainer.json to cause VS Code its sub-processes (terminals, tasks,
# debugging) to execute as the user. Uncomment the next line if you want the entire
# container to run as this user instead. Note that, on Linux, you may need to
# ensure the UID and GID of the container user you create matches your local user.
# See https://aka.ms/vscode-remote/containers/non-root for details.
#
# user: vscode

# Uncomment if you want to override the service's Dockerfile to one in the .devcontainer
# folder. Note that the path of the Dockerfile and context is relative to the *primary*
# docker-compose.yml file (the first in the devcontainer.json "dockerComposeFile"
# array). The sample below assumes your primary file is in the root of your project.
#
# build:
# context: .
# dockerfile: .devcontainer/Dockerfile
build: ./
# image: dev-image
# container_name: dev-container
volumes:
# Update this to wherever you want VS Code to mount the folder of your project
- ../:/workspace:cached

# Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details.
# - /var/run/docker.sock:/var/run/docker.sock

# Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
# cap_add:
# - SYS_PTRACE
# security_opt:
# - seccomp:unconfined

# Overrides default command so things don't shut down after the process ends.
command: /bin/sh -c "while sleep 1000; do :; done"
# postgres:
# image: postgres:13.1
# container_name: postgres-container
# environment:
# POSTGRES_PASSWORD: postgres
# volumes:
# - ./initdb/init.sql:/docker-entrypoint-initdb.d/init.sql
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.devcontainer
node_modules
dist
generated
24 changes: 24 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"env": {
"es2021": true,
"node": true,
"jest/globals": true
},
"extends": [
"standard",
"plugin:prettier/recommended",
"prettier/@typescript-eslint"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"@typescript-eslint",
"jest"
],
"rules": {
"node/no-callback-literal": "off"
}
}
21 changes: 21 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: release image
on:
release:
types: [published]
jobs:
push-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ secrets.CR_USER }}
password: ${{ secrets.CR_PAT }}
- name: Set Tag Name
run: echo "TAG_NAME=ghcr.io/twin-te/grpc-ts-template:${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Build
run: docker build . -t $TAG_NAME
- name: Push
run: docker push $TAG_NAME
16 changes: 16 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: test
on: [push]
jobs:
exec-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: start container
working-directory: .devcontainer
run: docker-compose up -d
- name: setup test
working-directory: .devcontainer
run: docker-compose exec -T node bash -c "yarn && yarn proto"
- name: run test
working-directory: .devcontainer
run: docker-compose exec -T node bash -c "yarn test"
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
generated
.coverage
dist
4 changes: 4 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"semi": false,
"singleQuote": true
}
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM node:14-slim AS build-env
WORKDIR /usr/src/app
COPY package.json ./
COPY yarn.lock ./
RUN yarn

COPY . .

RUN yarn proto

RUN yarn build


FROM node:14-alpine
WORKDIR /usr/src/app

LABEL org.opencontainers.image.source https://github.com/twin-te/grpc-ts-template

COPY --from=build-env /usr/src/app/dist ./dist
COPY --from=build-env /usr/src/app/protos ./protos
COPY --from=build-env /usr/src/app/generated ./generated
COPY --from=build-env /usr/src/app/package.json .
COPY --from=build-env /usr/src/app/yarn.lock .

RUN yarn install --prod

EXPOSE 50051

CMD ["node", "dist/index.js"]
71 changes: 71 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# grpc-ts-template

typescript & grpc のテンプレート。

# 推奨開発環境
docker + vscode を使うことで簡単に開発可能。

1. [RemoteDevelopment](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)拡張機能をインストール
2. このプロジェクトのフォルダを開く
3. 右下に `Folder contains a Dev Container configuration file. Reopen folder to develop in a container` と案内が表示されるので`Reopen in Container`を選択する。(表示されない場合はコマンドパレットを開き`open folder in container`と入力する)
4. node14の開発用コンテナが立ち上がりVSCodeで開かれる。また、`.devcontainer/docker-compose.yml` に任意のサービスを追加するとvscode起動時に一緒に起動できる(データベース等)。

# npmコマンド一覧

|コマンド|説明|
|:--|:--|
|dev| 開発起動|
|proto|protoファイルから型定義を生成(proto-gen.shを実行している)|
|client|grpcリクエストが送れるCLIを起動|
|test|テストを実行|
|build|distにビルド結果を出力|

# とりあえず動かす
```bash
# 準備
yarn && yarn proto

# 開発鯖立ち上げ
yarn dev


## ----以下別窓---- ##

# gRPCリクエストを送るCLIを立ち上げる
yarn client

# CLIが立ち上がったらリクエストを送る
HelloService@localhost:50051> client.greet({name: 'Twin:te'}, pr)

# レスポンスが返ってくれば成功
HelloService@localhost:50051>
{
"text": "hello! SIY1121"
}

```

# GitHub Actions
- `.github/workflows/test.yml` pushされるとテストを実行する
- `.github/workflows/release.yml` GitHub上でリリースをPublishするとDockerImageをビルドし、GHCRにプッシュする。

# 必要変更箇所

1. Dockerfile L17
```dockerfile
LABEL org.opencontainers.image.source https://github.com/twin-te/grpc-ts-template
```
後ろのurlを自分のレポジトリのurlに変更する。(DockerImageとレポジトリの紐付けを行う)

2. .github/workflows/release.yml L17
```yml
run: echo "TAG_NAME=ghcr.io/twin-te/grpc-ts-template:${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
```
TAG_NAME=ghcr.io/twin-te/{自分のレポジトリ名} に変更する(GitHubContainerRegistryにプッシュするときに使う)
3. GitHubのSettings > Secrets > New repository secret で以下の環境変数を登録(GitHubAction用)
|名前|説明|
|:---|:---|
|CR_PAT| GitHubContainerRegistry:write の権限を持ったPersonalAccessToken|
|CR_USER|PersonalAccessTokenを作ったユーザー名|
42 changes: 42 additions & 0 deletions __tests__/grpc/hello.service.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { startGrpcServer, stopGrpcServer } from '../../src/grpc'
import * as protoLoader from '@grpc/proto-loader'
import path from 'path'
import * as grpc from '@grpc/grpc-js'
import { HelloService } from '../../generated'
import { ServiceClientConstructor } from '@grpc/grpc-js/build/src/make-client'
import { GrpcClient } from '../../src/grpc/type'
import { Status } from '@grpc/grpc-js/build/src/constants'

const def = protoLoader.loadSync(
path.resolve(__dirname, `../../protos/HelloService.proto`)
)
const pkg = grpc.loadPackageDefinition(def)
const ClientConstructor = pkg.HelloService as ServiceClientConstructor
let client: GrpcClient<HelloService>

beforeAll(async () => {
await startGrpcServer()
client = (new ClientConstructor(
'localhost:50051',
grpc.ChannelCredentials.createInsecure()
) as unknown) as GrpcClient<HelloService>
})

test('greeting success', (done) => {
const name = 'Twin:te'
client.greet({ name }, (err, res) => {
expect(err).toBeNull()
expect(res?.text).toEqual(`hello! ${name}`)
done()
})
})

test('empty name', (done) => {
const name = ''
client.greet({ name }, (err, res) => {
expect(err?.code).toBe(Status.INVALID_ARGUMENT)
done()
})
})

afterAll(stopGrpcServer)
Loading

0 comments on commit baf0d5b

Please sign in to comment.