Skip to content

Commit

Permalink
Merge pull request #27 from EWHA-CAPSTONE-COOKSAVE/develop
Browse files Browse the repository at this point in the history
[배포][차소연] develop 브랜치를 main 브랜치로 머지
  • Loading branch information
Soyeon-Cha authored Jun 20, 2024
2 parents 7be7abc + a084d79 commit 1d4331c
Show file tree
Hide file tree
Showing 69 changed files with 2,363 additions and 1 deletion.
66 changes: 66 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Deploy to Amazon EC2

on:
push:
branches: [ "main" ]

env:
AWS_REGION: ap-northeast-2
S3_BUCKET_NAME: cooksave-github-actions-s3-bucket
CODE_DEPLOY_APPLICATION_NAME: cooksave-codedeploy-app
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: cooksave-codedeploy-deployment-group
APPLICATION: ${{ secrets.APPLICATION }}

permissions:
contents: read

jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment: production

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'

- name: make application.yml
run: |
mkdir ./src/main/resources
cd ./src/main/resources
touch ./application.yml
echo "${{ secrets.APPLICATION_YML }}" > ./application.yml
- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew build -x test
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

- name: Upload to AWS S3
run: |
aws deploy push \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--ignore-hidden-files \
--s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \
--source .
- name: Deploy to AWS EC2 from S3
run: |
aws deploy create-deployment \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ out/

### VS Code ###
.vscode/

### Application Settings ###
application.yml
application.properties
*.env
25 changes: 25 additions & 0 deletions appspec.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
version: 0.0
os: linux

files:
- source: /
destination: /home/ubuntu/spring
overwrite: yes
file_exists_behavior: OVERWRITE

permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu

hooks:
AfterInstall:
- location: scripts/stop.sh
timeout: 65
runas: ubuntu

ApplicationStart:
- location: scripts/start.sh
timeout: 65
runas: ubuntu
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,20 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'javax.xml.bind:jaxb-api:2.4.0-b180830.0359'
implementation 'com.googlecode.json-simple:json-simple:1.1.1'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
}

jar {
enabled = false
}

tasks.named('bootBuildImage') {
builder = 'paketobuildpacks/builder-jammy-base:latest'
}
Expand Down
21 changes: 21 additions & 0 deletions scripts/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash

PROJECT_ROOT="/home/ubuntu/spring"
JAR_FILE="$PROJECT_ROOT/cooksave-app.jar"

APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

# build 파일 복사
echo "$TIME_NOW > $JAR_FILE 파일 복사" >> $DEPLOY_LOG
cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE

# jar 파일 실행
echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &

CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG
19 changes: 19 additions & 0 deletions scripts/stop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash

PROJECT_ROOT="/home/ubuntu/spring"
JAR_FILE="$PROJECT_ROOT/cooksave-app.jar"

DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

# 현재 구동 중인 애플리케이션 pid 확인
CURRENT_PID=$(pgrep -f $JAR_FILE)

# 프로세스가 켜져 있으면 종료
if [ -z $CURRENT_PID ]; then
echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG
else
echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료" >> $DEPLOY_LOG
kill -15 $CURRENT_PID
fi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class CookSaveBackApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package CookSave.CookSaveback.Heart.controller;

import CookSave.CookSaveback.Heart.dto.HeartRecipeDto;
import CookSave.CookSaveback.Heart.service.HeartService;
import CookSave.CookSaveback.Member.domain.Member;
import CookSave.CookSaveback.Member.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/recipes")
public class HeartController {
private final MemberService memberService;
private final HeartService heartService;

// 레시피 찜 등록
@PostMapping("/{recipe_id}/hearts")
public ResponseEntity<String> heartRecipe(@PathVariable("recipe_id") Long recipeId){
Member member = memberService.getLoginMember();
String response = heartService.heartRecipe(member, recipeId);
return new ResponseEntity<>(response, HttpStatus.CREATED);
}

// 레시피 찜 취소
@DeleteMapping("/{recipe_id}/hearts")
public ResponseEntity<String> cancelRecipeHeart(@PathVariable("recipe_id") Long recipeId){
Member member = memberService.getLoginMember();
String response = heartService.cancelRecipeHeart(member, recipeId);
return new ResponseEntity<>(response, HttpStatus.OK);
}

// 찜한 레시피 목록 조회
@GetMapping("/saved")
@ResponseStatus(value = HttpStatus.OK)
public List<HeartRecipeDto> getHeartRecipeList(){
Member member = memberService.getLoginMember();
return heartService.getHeartRecipeList(member);
}
}
33 changes: 33 additions & 0 deletions src/main/java/CookSave/CookSaveback/Heart/domain/Heart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package CookSave.CookSaveback.Heart.domain;

import CookSave.CookSaveback.Member.domain.Member;
import CookSave.CookSaveback.Recipe.domain.Recipe;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Heart {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(nullable = false, updatable = false)
private Long heartId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", nullable = false)
private Member member;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "recipe_id", nullable = false)
private Recipe recipe;

@Builder
public Heart(Member member, Recipe recipe){
this.member = member;
this.recipe = recipe;
}
}
31 changes: 31 additions & 0 deletions src/main/java/CookSave/CookSaveback/Heart/dto/HeartRecipeDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package CookSave.CookSaveback.Heart.dto;

import CookSave.CookSaveback.Heart.domain.Heart;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.List;

@Getter
@NoArgsConstructor
public class HeartRecipeDto {
private Long heartId;
private Long memberId;
private Long recipeId;
private String name;
private String image;
private String mainIng;
private Boolean heart;

@Builder
public HeartRecipeDto(Heart heart){
this.heartId = heart.getHeartId();
this.memberId = heart.getMember().getMemberId();
this.recipeId = heart.getRecipe().getRecipeId();
this.name = heart.getRecipe().getName();
this.image = heart.getRecipe().getImage();
this.mainIng = heart.getRecipe().getMainIng();
this.heart = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package CookSave.CookSaveback.Heart.repository;

import CookSave.CookSaveback.Heart.domain.Heart;
import CookSave.CookSaveback.Member.domain.Member;
import CookSave.CookSaveback.Recipe.domain.Recipe;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface HeartRepository extends JpaRepository<Heart, Long> {
boolean existsByMemberAndRecipe(Member member, Recipe recipe);
Optional<Heart> findByMemberAndRecipe(Member member, Recipe recipe);
List<Heart> findAllByMember(Member member);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package CookSave.CookSaveback.Heart.service;

import CookSave.CookSaveback.Heart.domain.Heart;
import CookSave.CookSaveback.Heart.dto.HeartRecipeDto;
import CookSave.CookSaveback.Heart.repository.HeartRepository;
import CookSave.CookSaveback.Ingredient.domain.Ingredient;
import CookSave.CookSaveback.Ingredient.repository.IngredientRepository;
import CookSave.CookSaveback.Member.domain.Member;
import CookSave.CookSaveback.Recipe.domain.Recipe;
import CookSave.CookSaveback.Recipe.repository.RecipeRepository;
import CookSave.CookSaveback.RecipeTag.domain.RecipeTag;
import CookSave.CookSaveback.RecipeTag.repository.RecipeTagRepository;
import CookSave.CookSaveback.Tag.domain.Tag;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class HeartService {
private final HeartRepository heartRepository;
private final RecipeRepository recipeRepository;
private final IngredientRepository ingredientRepository;
private final RecipeTagRepository recipeTagRepository;

@Transactional
public String heartRecipe(Member member, Long recipeId){
Recipe recipe = recipeRepository.findById(recipeId)
.orElseThrow(() -> new EntityNotFoundException("recipeId가 " + recipeId + "인 레시피가 없습니다."));
if(heartRepository.existsByMemberAndRecipe(member, recipe)){
throw new RuntimeException("이미 저장 목록에 추가된 레시피입니다.");
}
else{
Heart heart = new Heart(member, recipe);
heartRepository.save(heart);
return "recipeId가 " + recipeId + "인 레시피가 찜 목록에 추가되었습니다.";
}
}

@Transactional
public String cancelRecipeHeart(Member member, Long recipeId){
Recipe recipe = recipeRepository.findById(recipeId)
.orElseThrow(() -> new EntityNotFoundException("recipeId가 " + recipeId + "인 레시피가 없습니다."));
Heart heart = heartRepository.findByMemberAndRecipe(member, recipe)
.orElseThrow(() -> new EntityNotFoundException("해당 레시피는 찜 목록에 존재하지 않습니다."));
heartRepository.delete(heart);
return "recipeId가 " + recipeId + "인 레시피가 찜 목록에서 제거되었습니다.";
}

public List<HeartRecipeDto> getHeartRecipeList(Member member){
List<HeartRecipeDto> heartRecipeDtoList = new ArrayList<>();

List<Heart> heartList = heartRepository.findAllByMember(member);

for (Heart heart : heartList){
heartRecipeDtoList.add(new HeartRecipeDto(heart));
}
return heartRecipeDtoList;
}
}
Loading

0 comments on commit 1d4331c

Please sign in to comment.