Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into develop
Browse files Browse the repository at this point in the history
# Conflicts:
#	.github/workflows/deploy-dev.yml
#	compose-blue.yml
#	compose-green.yml
  • Loading branch information
ingpyo committed Nov 22, 2023
2 parents d5be185 + ec151ad commit 5c7686f
Show file tree
Hide file tree
Showing 102 changed files with 2,052 additions and 575 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-be-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
uses: docker/build-push-action@v4
with:
context: ./backend
file: ./backend/Dockerfile
file: ./backend/Dockerfile-dev
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/dong-gle-backend-dev:latest
platforms: linux/arm64
Expand Down
13 changes: 2 additions & 11 deletions .github/workflows/build-be-prod.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
name: CICD for Backend Production

on:
push:
branches:
- main
paths:
- "backend/**"
workflow_call:
workflow_dispatch:

permissions:
Expand Down Expand Up @@ -62,12 +58,7 @@ jobs:
uses: docker/build-push-action@v4
with:
context: ./backend
file: ./backend/Dockerfile
file: ./backend/Dockerfile-prod
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/dong-gle-backend-prod:latest
platforms: linux/arm64

deploy:
needs: build
uses: ./.github/workflows/deploy-prod.yml
secrets: inherit
19 changes: 5 additions & 14 deletions .github/workflows/build-fe-prod.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
name: CICD for Frontend Production
name: CICD for Frontend Production

on:
push:
branches:
- main
paths:
- 'frontend/**'
workflow_call:
workflow_dispatch:

permissions:
Expand All @@ -19,15 +15,15 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18.x'
cache: 'yarn'
node-version: "18.x"
cache: "yarn"
cache-dependency-path: ${{ vars.FE_DIRECTORY }}/yarn.lock

- name: Install dependencies
run: |
yarn install --frozen-lockfile
working-directory: ${{ vars.FE_DIRECTORY }}

- name: Create .env.production variable
run: |
touch .env.production
Expand Down Expand Up @@ -57,8 +53,3 @@ jobs:
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/dong-gle-frontend-prod:latest
platforms: linux/arm64

deploy:
needs: build
uses: ./.github/workflows/deploy-prod.yml
secrets: inherit
1 change: 1 addition & 0 deletions .github/workflows/deploy-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ jobs:
sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
sudo chmod +x deploy.sh
sudo ./deploy.sh ${{ vars.INFRA_PROFILE_DEVELOPMENT }}
sudo docker image prune -af
41 changes: 24 additions & 17 deletions .github/workflows/deploy-prod.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
name: Run Docker Compose Production

on:
workflow_call:
workflow_dispatch:

permissions:
contents: read

jobs:
fe-build:
uses: ./.github/workflows/build-fe-prod.yml
secrets: inherit

be-build:
uses: ./.github/workflows/build-be-prod.yml
secrets: inherit

deploy:
runs-on: [self-hosted,prod]
runs-on: [self-hosted, prod]
needs: [fe-build, be-build]
steps:
- uses: actions/checkout@v3
- name: create .env
run: |
touch .env
echo "DOCKER_USERNAME=${{ secrets.DOCKER_USERNAME }}" >> .env
echo "SPRING_PROFILES_ACTIVE=${{ vars.SPRING_PROFILES_ACTIVE_PRODUCTION }}" >> .env
echo "INFRA_PROFILE=${{ vars.INFRA_PROFILE_PRODUCTION}}" >> .env
## deploy to production
- name: Deploy to prod
run: |
sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
sudo docker compose down
sudo docker compose pull
sudo docker compose up -d
sudo docker image prune -af
- uses: actions/checkout@v3
- name: create .env
run: |
touch .env
echo "DOCKER_USERNAME=${{ secrets.DOCKER_USERNAME }}" >> .env
echo "SPRING_PROFILES_ACTIVE=${{ vars.SPRING_PROFILES_ACTIVE_PRODUCTION }}" >> .env
echo "INFRA_PROFILE=${{ vars.INFRA_PROFILE_PRODUCTION}}" >> .env
## deploy to production
- name: Deploy to prod
run: |
sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
sudo chmod +x ./deploy.sh
sudo ./deploy.sh ${{ vars.INFRA_PROFILE_PRODUCTION }}
sudo docker image prune -af
5 changes: 3 additions & 2 deletions .github/workflows/fe-test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ jobs:
- name: Create .env.development file
run: |
touch .env.development
echo "BASE_URL=${{secrets.BASE_URL_DEVELOPMENT}}" >> .env.development
echo "BASE_URL=${{vars.API_SERVER_URL_DEVELOPMENT}}" >> .env.development
echo "DOMAIN_URL=${{vars.WEB_URL_DEVELOPMENT}}" >> .env.development
- name: Cypress run
uses: cypress-io/github-action@v5
with:
start: yarn start:mocking
wait-on: 'http://localhost:3000'
wait-on: "http://localhost:3000"
browser: chrome
working-directory: ./frontend
env:
Expand Down
4 changes: 0 additions & 4 deletions backend/Dockerfile

This file was deleted.

11 changes: 11 additions & 0 deletions backend/Dockerfile-dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Application stage
FROM amazoncorretto:17-alpine-jdk
EXPOSE 8080
COPY ./build/libs/backend-0.0.1-SNAPSHOT.jar /app.jar
ENTRYPOINT [ \
"java",\
"-javaagent:/javaagent/dd-java-agent.jar",\
"-jar",\
"-Duser.timezone=Asia/Seoul",\
"app.jar"\
]
10 changes: 10 additions & 0 deletions backend/Dockerfile-prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Application stage
FROM amazoncorretto:17-alpine-jdk
EXPOSE 8080
COPY ./build/libs/backend-0.0.1-SNAPSHOT.jar /app.jar
ENTRYPOINT [ \
"java",\
"-jar",\
"-Duser.timezone=Asia/Seoul",\
"app.jar"\
]
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package org.donggle.backend.application.client;

import org.donggle.backend.application.service.request.ImageUploadRequest;
import org.donggle.backend.application.service.request.PublishRequest;
import org.donggle.backend.domain.blog.BlogType;
import org.donggle.backend.ui.response.ImageUploadResponse;
import org.donggle.backend.ui.response.PublishResponse;

public interface BlogClient {

PublishResponse publish(String accessToken, String content, PublishRequest publishRequest, final String titleValue);

ImageUploadResponse uploadImage(String accessToken, ImageUploadRequest imageUploadRequest);

BlogType getBlogType();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.donggle.backend.application.client;

import org.springframework.core.io.buffer.DataBuffer;
import reactor.core.publisher.Flux;

import java.util.Optional;

public interface FileDownloadClient {
Optional<byte[]> download(String url);

Flux<DataBuffer> downloadAsFlux(String url);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.donggle.backend.infrastructure.file;
package org.donggle.backend.application.client;

import org.springframework.http.MediaType;

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.donggle.backend.application.service.publish;

import lombok.RequiredArgsConstructor;
import org.donggle.backend.application.client.FileDownloadClient;
import org.donggle.backend.application.service.request.ImageUploadRequest;
import org.donggle.backend.application.service.request.PublishRequest;
import org.donggle.backend.application.service.request.PublishWritingRequest;
import org.donggle.backend.domain.blog.Blog;
import org.donggle.backend.domain.blog.BlogClients;
import org.donggle.backend.domain.blog.BlogType;
import org.donggle.backend.domain.renderer.html.HtmlRenderer;
import org.donggle.backend.domain.writing.BlockType;
import org.donggle.backend.domain.writing.Writing;
import org.donggle.backend.domain.writing.block.Block;
import org.donggle.backend.domain.writing.block.Depth;
import org.donggle.backend.domain.writing.block.ImageBlock;
import org.donggle.backend.domain.writing.block.ImageUrl;
import org.donggle.backend.domain.writing.block.NormalBlock;
import org.donggle.backend.domain.writing.block.RawText;
import org.donggle.backend.ui.response.ImageUploadResponse;
import org.donggle.backend.ui.response.PublishResponse;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
@RequiredArgsConstructor
public class PublishFacadeService {
private final PublishService publishService;
private final HtmlRenderer htmlRenderer;
private final BlogClients blogClients;
private final FileDownloadClient fileDownloadClient;

public void publishWriting(final Long memberId, final Long writingId, final BlogType blogType, final PublishRequest publishRequest) {
final PublishWritingRequest request = publishService.findPublishWriting(memberId, writingId, blogType);
final Blog blog = request.blog();
final Writing writing = request.writing();
List<Block> blocks = writing.getBlocks();

if (blogType == BlogType.TISTORY) {
blocks = replaceTistoryImage(blogType, blocks, request.accessToken());
}

final String content = htmlRenderer.render(blocks);

final PublishResponse response = blogClients.publish(blogType, publishRequest, content, request.accessToken(), writing.getTitleValue());
publishService.saveProperties(blog, writing, response);
}

private List<Block> replaceTistoryImage(final BlogType blogType, final List<Block> blocks, final String accessToken) {
final List<Block> replacedBlocks = new ArrayList<>();
for (int i = 0; i < blocks.size(); i++) {
if (blocks.get(i).getBlockType() == BlockType.IMAGE) {
final ImageBlock imageBlock = (ImageBlock) blocks.get(i);
final ImageUrl imageUrl = imageBlock.getImageUrl();
final Flux<DataBuffer> imageData = fileDownloadClient.downloadAsFlux(imageUrl.getImageUrl());
final MediaType mediaType = parseMediaTypeFromFileName(imageUrl.getImageUrl());
final ImageUploadRequest imageUploadRequest = new ImageUploadRequest(imageData, mediaType);
final ImageUploadResponse imageUploadResponse = blogClients.uploadImage(blogType, accessToken, imageUploadRequest);
final NormalBlock imageReplacer = new NormalBlock(Depth.empty(), BlockType.PARAGRAPH, RawText.from(imageUploadResponse.replacer()), List.of());
replacedBlocks.add(imageReplacer);
} else {
replacedBlocks.add(blocks.get(i));
}
}
return replacedBlocks;
}

private MediaType parseMediaTypeFromFileName(final String fileName) {
return Optional.ofNullable(URLConnection.guessContentTypeFromName(fileName))
.map(MediaType::parseMediaType)
.orElseGet(() -> MediaType.APPLICATION_OCTET_STREAM);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package org.donggle.backend.application.service.blog;
package org.donggle.backend.application.service.publish;

import lombok.RequiredArgsConstructor;
import org.donggle.backend.application.repository.BlogRepository;
import org.donggle.backend.application.repository.BlogWritingRepository;
import org.donggle.backend.application.repository.MemberCredentialsRepository;
import org.donggle.backend.application.repository.MemberRepository;
import org.donggle.backend.application.repository.WritingRepository;
import org.donggle.backend.application.service.request.PublishWritingRequest;
import org.donggle.backend.domain.blog.Blog;
import org.donggle.backend.domain.blog.BlogType;
import org.donggle.backend.domain.blog.BlogWriting;
Expand Down Expand Up @@ -34,7 +35,7 @@

@Service
@Transactional
@RequiredArgsConstructor
@RequiredArgsConstructor()
public class PublishService {
private final BlogRepository blogRepository;
private final WritingRepository writingRepository;
Expand All @@ -46,8 +47,7 @@ public PublishWritingRequest findPublishWriting(final Long memberId, final Long
final Blog blog = findBlog(blogType);
final Member member = findMember(memberId);
final Writing writing = writingRepository.findByIdWithBlocks(writingId).orElseThrow(() -> new WritingNotFoundException(writingId));
findStylesByNomalBlocks(writing);

findStylesByNormalBlocks(writing);
validateAuthorization(member.getId(), writing);

final MemberCredentials memberCredentials = findMemberCredentials(member);
Expand All @@ -58,18 +58,21 @@ public PublishWritingRequest findPublishWriting(final Long memberId, final Long
return new PublishWritingRequest(blog, writing, accessToken);
}

private void findStylesByNomalBlocks(final Writing writing) {
final List<Block> blocks = writing.getBlocks();
final Set<BlockType> notNormalType = Set.of(CODE_BLOCK, IMAGE, HORIZONTAL_RULES);
final List<NormalBlock> normalBlocks = blocks.stream().filter(block -> !notNormalType.contains(block.getBlockType())).map(NormalBlock.class::cast).toList();
writingRepository.findStylesForBlocks(normalBlocks);
}

public void saveProperties(final Blog blog, final Writing writing, final PublishResponse response) {
blogWritingRepository.save(new BlogWriting(blog, writing, response.dateTime(), response.tags(), response.url()));
}


private void findStylesByNormalBlocks(final Writing writing) {
final List<Block> blocks = writing.getBlocks();
final Set<BlockType> notNormalType = Set.of(CODE_BLOCK, IMAGE, HORIZONTAL_RULES);
final List<NormalBlock> normalBlocks = blocks.stream()
.filter(block -> !notNormalType.contains(block.getBlockType()))
.map(NormalBlock.class::cast)
.toList();
writingRepository.findStylesForBlocks(normalBlocks);
}

private MemberCredentials findMemberCredentials(final Member member) {
return memberCredentialsRepository.findByMember(member).orElseThrow(NoSuchElementException::new);
}
Expand Down
Loading

0 comments on commit 5c7686f

Please sign in to comment.