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

[Feat] #20 인플루언서 추가 수정 삭제 기능 + CI/CD 환경변수 추가했어요 #43

Merged
merged 7 commits into from
Oct 9, 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
83 changes: 39 additions & 44 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,50 +6,50 @@ on:
branches: [ "Master", "develop", "weekly/*" ]

permissions:
contents: read
contents: read

jobs:
# Spring Boot 애플리케이션을 빌드하여 도커허브에 푸시하는 과정
build-docker-image:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
# Java 17 세팅
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

# Gradle Wrapper 파일 실행 권한 주기
- name: Run chmod to make gradlew executable
run: chmod +x ./gradlew

# Spring Boot 애플리케이션 빌드
- name: Build with Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: clean bootJar

# 테스트 실행
# - name: Run tests
# run: ./gradlew test

# Docker 이미지 빌드
- name: docker image build
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/inplace .

# DockerHub 로그인
- name: docker login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}

# Docker Hub 이미지 푸시
- name: docker Hub push
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/inplace
- uses: actions/checkout@v4
# Java 17 세팅
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'

# Gradle Wrapper 파일 실행 권한 주기
- name: Run chmod to make gradlew executable
run: chmod +x ./gradlew

# Spring Boot 애플리케이션 빌드
- name: Build with Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: clean bootJar

# 테스트 실행
# - name: Run tests
# run: ./gradlew test

# Docker 이미지 빌드
- name: docker image build
run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/inplace .

# DockerHub 로그인
- name: docker login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}

# Docker Hub 이미지 푸시
- name: docker Hub push
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/inplace


# 위 과정에서 푸시한 이미지를 ec2에서 풀받아서 실행시키는 과정
Expand All @@ -73,12 +73,7 @@ jobs:
# .env 파일 생성
- name: Create .env file
run: |
echo "KAKAO_CLIENT_ID=${{ secrets.KAKAO_CLIENT_ID }}" >> .env
echo "KAKAO_CLIENT_SECRET=${{ secrets.KAKAO_CLIENT_SECRET }}" >> .env
echo "KAKAO_REDIRECT_URI=${{ secrets.KAKAO_REDIRECT_URI }}" >> .env
echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> .env
echo "JWT_ACCESS_TOKEN_EXPIRED_TIME=${{ secrets.JWT_ACCESS_TOKEN_EXPIRED_TIME }}" >> .env
echo "JWT_REFRESH_TOKEN_EXPIRED_TIME=${{ secrets.JWT_REFRESH_TOKEN_EXPIRED_TIME }}" >> .env
echo "${{ secrets.ENV }}" >> .env

# 브랜치에 따라 다른 환경 변수를 설정하여 컨테이너 실행
- name: docker run new container
Expand All @@ -88,7 +83,7 @@ jobs:
elif [ "${{ github.ref }}" == "refs/heads/develop" ]; then
sudo docker run --name inplace-dev --rm -d -p 8081:8080 --env-file .env ${{ secrets.DOCKERHUB_USERNAME }}/inplace
fi

# 미사용 이미지를 정리
- name: delete old docker image
run: sudo docker system prune -f
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
package team7.inplace.influencer.application;

import java.util.List;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import team7.inplace.global.exception.InplaceException;
import team7.inplace.global.exception.code.AuthorizationErrorCode;
import team7.inplace.influencer.application.dto.InfluencerCommand;
import team7.inplace.influencer.application.dto.InfluencerInfo;
import team7.inplace.influencer.domain.Influencer;
import team7.inplace.influencer.persistence.InfluencerRepository;
import team7.inplace.influencer.presentation.dto.InfluencerRequestParam;
import team7.inplace.userFavoriteInfluencer.domain.UserFavoriteInfluencer;
import team7.inplace.userFavoriteInfluencer.persistent.UserFavoriteInfluencerRepository;
import team7.inplace.security.util.AuthorizationUtil;
import team7.inplace.user.domain.User;
import team7.inplace.user.persistence.UserRepository;
import team7.inplace.userFavoriteInfluencer.domain.UserFavoriteInfluencer;
import team7.inplace.userFavoriteInfluencer.persistent.UserFavoriteInfluencerRepository;

@RequiredArgsConstructor
@Service
Expand All @@ -33,9 +33,31 @@ public List<InfluencerInfo> getAllInfluencers() {
.toList();
}

public void likeToInfluencer(InfluencerRequestParam param){
@Transactional
public Long createInfluencer(InfluencerCommand command) {
Influencer influencer = InfluencerCommand.to(command);
return influencerRepository.save(influencer).getId();
}

@Transactional
public Long updateInfluencer(Long id, InfluencerCommand command) {
Influencer influencer = influencerRepository.findById(id).orElseThrow();
influencer.update(command.influencerName(), command.influencerImgUrl(),
command.influencerJob());

return influencer.getId();
}

@Transactional
public void deleteInfluencer(Long id) {
Influencer influencer = influencerRepository.findById(id).orElseThrow();

influencerRepository.delete(influencer);
}

public void likeToInfluencer(InfluencerRequestParam param) {
String username = AuthorizationUtil.getUsername();
if(StringUtils.hasText(username)){
if (StringUtils.hasText(username)) {
throw InplaceException.of(AuthorizationErrorCode.TOKEN_IS_EMPTY);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package team7.inplace.influencer.application.dto;

import team7.inplace.influencer.domain.Influencer;

public record InfluencerCommand(
String influencerName,
String influencerImgUrl,
String influencerJob
) {

public static Influencer to(InfluencerCommand influencerCommand) {
return new Influencer(
influencerCommand.influencerName,
influencerCommand.influencerImgUrl,
influencerCommand.influencerJob
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ public class InfluencerDataLoader implements ApplicationRunner {

@Override
public void run(ApplicationArguments args) throws Exception {
Influencer influencer1 = new Influencer("Influencer 1", "job1", "imgUrl1");
Influencer influencer2 = new Influencer("Influencer 2", "job2", "imgUrl2");
Influencer influencer3 = new Influencer("Influencer 3", "job3", "imgUrl3");
Influencer influencer1 = new Influencer("Influencer 1", "imgUrl1", "job1");
Influencer influencer2 = new Influencer("Influencer 2", "imgUrl2", "job2");
Influencer influencer3 = new Influencer("Influencer 3", "imgUrl3", "job3");

influencerRepository.save(influencer1);
influencerRepository.save(influencer2);
Expand Down
12 changes: 9 additions & 3 deletions src/main/java/team7/inplace/influencer/domain/Influencer.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Builder;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = PROTECTED)
@AllArgsConstructor
@Entity
public class Influencer {

Expand All @@ -29,10 +30,15 @@ public class Influencer {
@Column(nullable = false, columnDefinition = "TEXT")
private String imgUrl;

@Builder
public Influencer(String name, String job, String imgUrl) {
public Influencer(String name, String imgUrl, String job) {
this.name = name;
this.imgUrl = imgUrl;
this.job = job;
}

public void update(String name, String imgUrl, String job) {
this.name = name;
this.imgUrl = imgUrl;
this.job = job;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,25 @@
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import team7.inplace.influencer.application.InfluencerService;
import team7.inplace.influencer.application.dto.InfluencerCommand;
import team7.inplace.influencer.application.dto.InfluencerInfo;
import team7.inplace.influencer.presentation.dto.InfluencerListResponse;
import team7.inplace.influencer.presentation.dto.InfluencerRequest;
import team7.inplace.influencer.presentation.dto.InfluencerRequestParam;
import team7.inplace.influencer.presentation.dto.InfluencerResponse;

@RequiredArgsConstructor
@RestController
@RequestMapping("/influencers")
public class InfluencerController {
public class InfluencerController implements InfluencerControllerApiSpec {

private final InfluencerService influencerService;

Expand All @@ -29,10 +37,40 @@ public ResponseEntity<InfluencerListResponse> getAllInfluencers() {
return new ResponseEntity<>(response, HttpStatus.OK);
}

@PostMapping("/influencers")
public ResponseEntity<Long> createInfluencer(@RequestBody InfluencerRequest request) {
InfluencerCommand influencerCommand = new InfluencerCommand(
request.influencerName(),
request.influencerImgUrl(),
request.influencerJob()
);
Long savedId = influencerService.createInfluencer(influencerCommand);

return new ResponseEntity<>(savedId, HttpStatus.OK);
}

@PutMapping("/influencers/{id}")
public ResponseEntity<Long> updateInfluencer(@PathVariable Long id,
@RequestBody InfluencerRequest request) {
InfluencerCommand influencerCommand = new InfluencerCommand(
request.influencerName(),
request.influencerImgUrl(),
request.influencerJob()
);
Long updatedId = influencerService.updateInfluencer(id, influencerCommand);

return new ResponseEntity<>(updatedId, HttpStatus.OK);
}

@DeleteMapping("/influencers/{id}")
public ResponseEntity<Long> deleteInfluencer(@PathVariable Long id) {
influencerService.deleteInfluencer(id);

return new ResponseEntity<>(id, HttpStatus.OK);
}

@PostMapping("/likes")
public ResponseEntity<Void> likeToInfluencer(
@ModelAttribute InfluencerRequestParam param
) {
public ResponseEntity<Void> likeToInfluencer(@ModelAttribute InfluencerRequestParam param) {
influencerService.likeToInfluencer(param);
return new ResponseEntity<>(HttpStatus.OK);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package team7.inplace.influencer.presentation;

import io.swagger.v3.oas.annotations.Operation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import team7.inplace.influencer.presentation.dto.InfluencerListResponse;
import team7.inplace.influencer.presentation.dto.InfluencerRequest;

public interface InfluencerControllerApiSpec {

@Operation(summary = "인플루언서들 리스트 반환", description = "토큰 유무에 따라 좋아요한 인플루언서 반영 여부가 다릅니다.")
ResponseEntity<InfluencerListResponse> getAllInfluencers();

@Operation(summary = "인플루언서 등록", description = "새 인플루언서를 등록합니다.")
ResponseEntity<Long> createInfluencer(@RequestBody InfluencerRequest request);

@Operation(summary = "인플루언서 수정", description = "인플루언서를 수정합니다.")
ResponseEntity<Long> updateInfluencer(@PathVariable Long id,
@RequestBody InfluencerRequest request);

@Operation(summary = "인플루언서 삭제", description = "인플루언서를 삭제합니다.")
ResponseEntity<Long> deleteInfluencer(@PathVariable Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package team7.inplace.influencer.presentation.dto;

public record InfluencerRequest(
String influencerName,
String influencerImgUrl,
String influencerJob
) {

}
2 changes: 1 addition & 1 deletion src/main/resources/application-db.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ spring:
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: create-drop
ddl-auto: none
properties:
hibernate:
format_sql: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,9 @@ public class InfluencerRepositoryTest {

@Test
public void findAllTest() {
Influencer influencer1 = Influencer.builder()
.name("influencer1")
.job("job1")
.imgUrl("imgUrl1")
.build();
Influencer influencer2 = Influencer.builder()
.name("influencer2")
.job("job2")
.imgUrl("imgUrl2")
.build();
Influencer influencer1 = new Influencer("influencer1", "imgUrl1", "job1");
Influencer influencer2 = new Influencer("influencer2", "imgUrl2", "job2");

influencerRepository.save(influencer1);
influencerRepository.save(influencer2);

Expand Down
Loading