Skip to content

Commit 11ecccc

Browse files
committed
Adiciona workflow para deploy (#5)
1 parent fc7b3f4 commit 11ecccc

File tree

6 files changed

+187
-38
lines changed

6 files changed

+187
-38
lines changed

.github/workflows/deployment.yaml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Deploy
2+
on:
3+
push:
4+
branches:
5+
- master
6+
workflow_dispatch:
7+
8+
jobs:
9+
deploy:
10+
name: Deploy
11+
runs-on: ubuntu-latest
12+
env:
13+
AWS_INSTANCE_SG_ID: ${{ secrets.AWS_INSTANCE_SG_ID }}
14+
steps:
15+
- name: Configure AWS Credentials
16+
uses: aws-actions/configure-aws-credentials@v1
17+
with:
18+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
19+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
20+
aws-region: ${{ secrets.AWS_REGION }}
21+
- name: Get Runner IP Address
22+
id: ip
23+
uses: haythem/[email protected]
24+
- name: Add IP to security group ingress
25+
run: |
26+
aws ec2 authorize-security-group-ingress \
27+
--group-id $AWS_INSTANCE_SG_ID \
28+
--protocol tcp \
29+
--port 22 \
30+
--cidr ${{ steps.ip.outputs.ipv4 }}/32
31+
- name: Execute SSH
32+
uses: appleboy/[email protected]
33+
with:
34+
host: ${{ secrets.SSH_HOST }}
35+
username: ${{ secrets.SSH_USER }}
36+
key: ${{ secrets.SSH_KEY }}
37+
port: ${{ secrets.SSH_PORT }}
38+
script: |
39+
cd quebradev-api \
40+
&& ./bin/rolling-update.sh
41+
- name: Remove IP from security group
42+
run: |
43+
aws ec2 revoke-security-group-ingress \
44+
--group-id $AWS_INSTANCE_SG_ID \
45+
--protocol tcp \
46+
--port 22 \
47+
--cidr ${{ steps.ip.outputs.ipv4 }}/32
48+

bin/rolling-update.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
PREVIOUS_CONTAINER=$(docker ps --format "table {{.ID}} {{.Names}} {{.CreatedAt}}" | grep quebradev-api | awk -F " " '{print $1}')
2+
3+
echo "Starting rolling update"
4+
docker ps --format "table {{.ID}} {{.Names}} {{.CreatedAt}}"
5+
6+
git pull origin master \
7+
&& docker-compose -f docker-compose.production.yaml up -d --remove-orphans --no-deps --scale api=2 --no-recreate api \
8+
&& docker-compose -f docker-compose.production.yaml exec nginx nginx -s reload \
9+
&& docker kill -s SIGTERM $PREVIOUS_CONTAINER \
10+
&& docker-compose -f docker-compose.production.yaml up -d --remove-orphans --no-deps --scale api=1 --no-recreate api
11+
12+
echo "Rolling update done"
13+
docker ps --format "table {{.ID}} {{.Names}} {{.CreatedAt}}"

docker-compose.production.yaml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
services:
2+
api:
3+
build: .
4+
command: npm run start
5+
environment:
6+
BASIC_AUTH_PASSWORD: ${BASIC_AUTH_PASSWORD:-}
7+
MONGODB_URI: mongodb://root:password@mongo
8+
AWS_REGION: us-east-1
9+
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-}
10+
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-}
11+
AWS_BUCKET_NAME: certificados-quebradev
12+
AWS_ENDPOINT: http://s3.amazonaws.com
13+
depends_on:
14+
- mongo
15+
volumes:
16+
- /home/node/app/node_modules
17+
- ./:/home/node/app
18+
19+
mongo:
20+
image: mongo
21+
container_name: quebradev-mongodb
22+
restart: always
23+
environment:
24+
MONGO_INITDB_ROOT_USERNAME: root
25+
MONGO_INITDB_ROOT_PASSWORD: password
26+
volumes:
27+
- mongodb:/data/db
28+
29+
nginx:
30+
image: nginx:1.15-alpine
31+
container_name: quebradev-nginx
32+
command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
33+
ports:
34+
- "80:80"
35+
- "443:443"
36+
volumes:
37+
- ./nginx:/etc/nginx/conf.d
38+
- ./data/certbot/conf:/etc/letsencrypt
39+
- ./data/certbot/www:/var/www/certbot
40+
41+
certbot:
42+
image: certbot/certbot
43+
container_name: quebradev-certbot
44+
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
45+
volumes:
46+
- ./data/certbot/conf:/etc/letsencrypt
47+
- ./data/certbot/www:/var/www/certbot
48+
49+
volumes:
50+
mongodb:

nginx/app.conf

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
limit_req_zone $binary_remote_addr zone=apilimit:10m rate=10r/s;
2+
3+
server {
4+
listen 80;
5+
server_name api.quebra.dev;
6+
7+
location / {
8+
return 301 https://$host$request_uri;
9+
}
10+
11+
location /.well-known/acme-challenge/ {
12+
root /var/www/certbot;
13+
}
14+
}
15+
16+
server {
17+
listen 443 ssl;
18+
server_name api.quebra.dev;
19+
ssl_certificate /etc/letsencrypt/live/api.quebra.dev/fullchain.pem;
20+
ssl_certificate_key /etc/letsencrypt/live/api.quebra.dev/privkey.pem;
21+
include /etc/letsencrypt/options-ssl-nginx.conf;
22+
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
23+
24+
location / {
25+
limit_req zone=apilimit;
26+
proxy_pass http://api:3000;
27+
}
28+
}

src/controllers/certified.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ exports.post = (req, res, next) => {
2727
});
2828
});
2929
}).catch((error) => {
30-
res.status(400).json(error);
30+
res.status(400).json({"error": error});
3131
});
3232
}

src/services/certificateService.js

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,40 +17,45 @@ const s3Client = new S3({
1717
const createCertificate = async (certificate, hash) => {
1818
const params = { Bucket: process.env.AWS_BUCKET_NAME, Key: 'bases/certificado-base.png', };
1919

20-
return new Promise((resolve) => {
20+
return new Promise((resolve, reject) => {
2121
s3Client.getObject(params, async (error, data) => {
2222
if (error) {
2323
reject(error);
2424
return;
2525
}
26-
27-
const canvas = Canvas.createCanvas(1600, 1194);
28-
let canvasContext = canvas.getContext('2d');
29-
const canvasImage = new Canvas.Image();
30-
const courseDates = getCourseDates(certificate.period.dates);
31-
32-
canvasImage.src = Buffer.from(await data.Body.transformToByteArray());
33-
34-
if (certificate.type.name == "student") {
35-
buildCertificateToStudent(canvasContext, canvasImage, canvas, certificate, hash, courseDates);
36-
canvasContext = await addSignatureToCertificate(canvasContext, certificate.course.responsibles);
37-
}
3826

39-
if (certificate.type.name == "author" || certificate.type.name == "speaker") {
40-
buildCertificateToAuthorOrSpeaker(
41-
canvasContext, canvasImage, canvas,
42-
certificate, hash, courseDates
43-
);
44-
canvasContext = await addSignatureToCertificate(canvasContext, certificate.course.responsibles);
45-
}
27+
try {
28+
const canvas = Canvas.createCanvas(1600, 1194);
29+
let canvasContext = canvas.getContext('2d');
30+
const canvasImage = new Canvas.Image();
31+
const courseDates = getCourseDates(certificate.period.dates);
32+
33+
canvasImage.src = Buffer.from(await data.Body.transformToByteArray());
34+
35+
if (certificate.type.name == "student") {
36+
buildCertificateToStudent(canvasContext, canvasImage, canvas, certificate, hash, courseDates);
37+
canvasContext = await addSignatureToCertificate(canvasContext, certificate.course.responsibles);
38+
}
4639

47-
if (certificate.type.name == "teacher") {
48-
// todo
40+
if (certificate.type.name == "author" || certificate.type.name == "speaker") {
41+
buildCertificateToAuthorOrSpeaker(
42+
canvasContext, canvasImage, canvas,
43+
certificate, hash, courseDates
44+
);
45+
canvasContext = await addSignatureToCertificate(canvasContext, certificate.course.responsibles);
46+
}
47+
48+
if (certificate.type.name == "teacher") {
49+
// todo
50+
}
51+
52+
const certificateOut = fs.createWriteStream(path.join(__dirname, `/../images/${hash}.png`));
53+
canvas.createPNGStream().pipe(certificateOut);
54+
certificateOut.on('finish', () => resolve(true));
55+
} catch (e) {
56+
console.error(e);
57+
reject(e.message);
4958
}
50-
51-
const certificateOut = fs.createWriteStream(path.join(__dirname, `/../images/${hash}.png`));
52-
canvas.createPNGStream().pipe(certificateOut);
53-
certificateOut.on('finish', () => resolve(true));
5459
})
5560
});
5661
}
@@ -161,17 +166,22 @@ const addSignatureToCertificate = async (certificateCanvas, responsibles) => {
161166
const uploadCertificate = (hash) => {
162167
const certificatePath = path.join(__dirname, `/../images/${hash}.png`);
163168

164-
return new Promise((resolve) => {
165-
s3Client.putObject({
166-
Bucket: process.env.AWS_BUCKET_NAME,
167-
Key: `certificados/${hash}.png`,
168-
Body: fs.readFileSync(certificatePath),
169-
}, async function(error, data) {
170-
if (error) return console.log('Upload error: ', err.message);
171-
fs.unlink(certificatePath, () => console.log('Certificado emitido.'));
172-
173-
resolve(await getCertificateImageSignedUrl(hash));
174-
});
169+
return new Promise((resolve, reject) => {
170+
try {
171+
s3Client.putObject({
172+
Bucket: process.env.AWS_BUCKET_NAME,
173+
Key: `certificados/${hash}.png`,
174+
Body: fs.readFileSync(certificatePath),
175+
}, async function(error, data) {
176+
if (error) return console.log('Upload error: ', err.message);
177+
fs.unlink(certificatePath, () => console.log('Certificado emitido.'));
178+
179+
resolve(await getCertificateImageSignedUrl(hash));
180+
});
181+
} catch (e) {
182+
console.error(e);
183+
reject(e.message)
184+
}
175185
})
176186
}
177187

0 commit comments

Comments
 (0)