Skip to content
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
66 changes: 59 additions & 7 deletions .github/workflows/version-check.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,71 @@
name: Version Check & Release PR
name: Version Tag Sync

on:
push:
branches: [main]
paths:
- '**/VERSION'

concurrency:
group: version-check
group: version-tag-sync
cancel-in-progress: true

permissions:
contents: write
pull-requests: write

jobs:
check-and-create-pr:
create-tag:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- module: product
version_file: bottlenote-product-api/VERSION
- module: admin
version_file: bottlenote-admin-api/VERSION
- module: batch
version_file: bottlenote-batch/VERSION

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 2

- name: Check VERSION file changed
id: version-change
run: |
if git diff --name-only HEAD~1 HEAD | grep -q "${{ matrix.version_file }}"; then
VERSION=$(cat "${{ matrix.version_file }}" | tr -d '[:space:]')
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "${{ matrix.module }} VERSION changed: $VERSION"
else
echo "changed=false" >> "$GITHUB_OUTPUT"
echo "${{ matrix.module }} VERSION not changed, skipping"
fi

- name: Create and push tag
if: steps.version-change.outputs.changed == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

VERSION="${{ steps.version-change.outputs.version }}"
MODULE="${{ matrix.module }}"
TAG_NAME="${MODULE}/v${VERSION}"

if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
echo "Tag $TAG_NAME already exists, skipping"
else
git tag -a "$TAG_NAME" -m "Release ${MODULE} v${VERSION}"
git push origin "$TAG_NAME"
echo "Created and pushed tag: $TAG_NAME"
fi

create-release-pr:
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand Down Expand Up @@ -82,7 +134,7 @@ jobs:
id: existing-version
run: |
PR_TITLE="${{ steps.existing-pr.outputs.pr_title }}"
EXISTING_VERSION=$(echo "$PR_TITLE" | grep -oP 'v\K[0-9]+\.[0-9]+\.[0-9]+' || echo "0.0.0")
EXISTING_VERSION=$(echo "$PR_TITLE" | grep -oP 'v\K[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?' || echo "0.0.0")
echo "version=$EXISTING_VERSION" >> "$GITHUB_OUTPUT"
echo "Existing PR version: $EXISTING_VERSION"

Expand All @@ -94,7 +146,7 @@ jobs:
OLD_VERSION="${{ steps.existing-version.outputs.version }}"

version_to_int() {
echo "$1" | awk -F. '{ printf("%d%03d%03d", $1, $2, $3) }'
echo "$1" | awk -F'[-.]' '{ printf("%d%03d%03d%03d", $1, $2, $3, (NF>=4 ? $4 : 0)) }'
}

NEW_INT=$(version_to_int "$NEW_VERSION")
Expand Down Expand Up @@ -142,7 +194,7 @@ jobs:
- **Auto-generated release PR**

---
This PR was automatically created by version-check workflow.
This PR was automatically created by version-tag-sync workflow.
EOF
)

Expand Down Expand Up @@ -173,7 +225,7 @@ jobs:
- **Auto-generated release PR**

---
This PR was automatically created by version-check workflow.
This PR was automatically created by version-tag-sync workflow.
EOF
)

Expand Down
2 changes: 1 addition & 1 deletion bottlenote-admin-api/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.7-3
1.0.8
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@
import lombok.Builder;

public record AdminBannerCreateRequest(
@NotBlank(message = "배너명은 필수입니다.") String name,
@Pattern(regexp = "^#[0-9a-fA-F]{6}$", message = "HEX 색상 형식이 올바르지 않습니다.") String nameFontColor,
@Size(max = 50, message = "배너 설명은 최대 50자까지 가능합니다.") String descriptionA,
@Size(max = 50, message = "배너 설명은 최대 50자까지 가능합니다.") String descriptionB,
@Pattern(regexp = "^#[0-9a-fA-F]{6}$", message = "HEX 색상 형식이 올바르지 않습니다.")
@NotBlank(message = "BANNER_NAME_REQUIRED") String name,
@Pattern(regexp = "^#[0-9a-fA-F]{6}$", message = "INVALID_HEX_COLOR_FORMAT") String nameFontColor,
@Size(max = 50, message = "BANNER_DESCRIPTION_MAX_SIZE") String descriptionA,
@Size(max = 50, message = "BANNER_DESCRIPTION_MAX_SIZE") String descriptionB,
@Pattern(regexp = "^#[0-9a-fA-F]{6}$", message = "INVALID_HEX_COLOR_FORMAT")
String descriptionFontColor,
@NotBlank(message = "이미지 URL은 필수입니다.") String imageUrl,
@NotBlank(message = "BANNER_IMAGE_URL_REQUIRED") String imageUrl,
TextPosition textPosition,
Boolean isExternalUrl,
String targetUrl,
@NotNull(message = "배너 유형은 필수입니다.") BannerType bannerType,
@Min(value = 0, message = "정렬 순서는 0 이상이어야 합니다.") Integer sortOrder,
@NotNull(message = "BANNER_TYPE_REQUIRED") BannerType bannerType,
@Min(value = 0, message = "BANNER_SORT_ORDER_MINIMUM") Integer sortOrder,
LocalDateTime startDate,
LocalDateTime endDate) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
import jakarta.validation.constraints.NotNull;

public record AdminBannerSortOrderRequest(
@NotNull(message = "정렬 순서는 필수입니다.") @Min(value = 0, message = "정렬 순서는 0 이상이어야 합니다.")
@NotNull(message = "BANNER_SORT_ORDER_REQUIRED") @Min(value = 0, message = "BANNER_SORT_ORDER_MINIMUM")
Integer sortOrder) {}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

import jakarta.validation.constraints.NotNull;

public record AdminBannerStatusRequest(@NotNull(message = "활성화 상태는 필수입니다.") Boolean isActive) {}
public record AdminBannerStatusRequest(@NotNull(message = "BANNER_IS_ACTIVE_REQUIRED") Boolean isActive) {}
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@
import java.time.LocalDateTime;

public record AdminBannerUpdateRequest(
@NotBlank(message = "배너명은 필수입니다.") String name,
@Pattern(regexp = "^#[0-9a-fA-F]{6}$", message = "HEX 색상 형식이 올바르지 않습니다.") String nameFontColor,
@Size(max = 50, message = "배너 설명은 최대 50자까지 가능합니다.") String descriptionA,
@Size(max = 50, message = "배너 설명은 최대 50자까지 가능합니다.") String descriptionB,
@Pattern(regexp = "^#[0-9a-fA-F]{6}$", message = "HEX 색상 형식이 올바르지 않습니다.")
@NotBlank(message = "BANNER_NAME_REQUIRED") String name,
@Pattern(regexp = "^#[0-9a-fA-F]{6}$", message = "INVALID_HEX_COLOR_FORMAT") String nameFontColor,
@Size(max = 50, message = "BANNER_DESCRIPTION_MAX_SIZE") String descriptionA,
@Size(max = 50, message = "BANNER_DESCRIPTION_MAX_SIZE") String descriptionB,
@Pattern(regexp = "^#[0-9a-fA-F]{6}$", message = "INVALID_HEX_COLOR_FORMAT")
String descriptionFontColor,
@NotBlank(message = "이미지 URL은 필수입니다.") String imageUrl,
@NotBlank(message = "BANNER_IMAGE_URL_REQUIRED") String imageUrl,
TextPosition textPosition,
Boolean isExternalUrl,
String targetUrl,
@NotNull(message = "배너 유형은 필수입니다.") BannerType bannerType,
@NotNull(message = "정렬 순서는 필수입니다.") @Min(value = 0, message = "정렬 순서는 0 이상이어야 합니다.")
@NotNull(message = "BANNER_TYPE_REQUIRED") BannerType bannerType,
@NotNull(message = "BANNER_SORT_ORDER_REQUIRED") @Min(value = 0, message = "BANNER_SORT_ORDER_MINIMUM")
Integer sortOrder,
LocalDateTime startDate,
LocalDateTime endDate,
@NotNull(message = "활성화 상태는 필수입니다.") Boolean isActive) {}
@NotNull(message = "BANNER_IS_ACTIVE_REQUIRED") Boolean isActive) {}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,17 @@ public enum ValidExceptionCode implements ExceptionCode {
// HELP
HELP_TITLE_REQUIRED(HttpStatus.BAD_REQUEST, "문의글 제목은 필수입니다."),
HELP_CONTENT_REQUIRED(HttpStatus.BAD_REQUEST, "문의글 내용은 필수입니다."),
REQUIRED_HELP_TYPE(HttpStatus.BAD_REQUEST, "문의 유형은 필수입니다.(WHISKEY, REVIEW, USER, ETC)");
REQUIRED_HELP_TYPE(HttpStatus.BAD_REQUEST, "문의 유형은 필수입니다.(WHISKEY, REVIEW, USER, ETC)"),

// BANNER
BANNER_NAME_REQUIRED(HttpStatus.BAD_REQUEST, "배너명은 필수입니다."),
INVALID_HEX_COLOR_FORMAT(HttpStatus.BAD_REQUEST, "HEX 색상 형식이 올바르지 않습니다."),
BANNER_DESCRIPTION_MAX_SIZE(HttpStatus.BAD_REQUEST, "배너 설명은 최대 50자까지 가능합니다."),
BANNER_IMAGE_URL_REQUIRED(HttpStatus.BAD_REQUEST, "이미지 URL은 필수입니다."),
BANNER_TYPE_REQUIRED(HttpStatus.BAD_REQUEST, "배너 유형은 필수입니다."),
BANNER_SORT_ORDER_REQUIRED(HttpStatus.BAD_REQUEST, "정렬 순서는 필수입니다."),
BANNER_SORT_ORDER_MINIMUM(HttpStatus.BAD_REQUEST, "정렬 순서는 0 이상이어야 합니다."),
BANNER_IS_ACTIVE_REQUIRED(HttpStatus.BAD_REQUEST, "활성화 상태는 필수입니다.");

private final HttpStatus httpStatus;
private String message;
Expand Down
2 changes: 1 addition & 1 deletion bottlenote-product-api/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.6
1.0.7-3
2 changes: 1 addition & 1 deletion git.environment-variables
77 changes: 77 additions & 0 deletions http/admin/04_배너관리/배너.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
### 배너 목록 조회
GET {{host}}/banners?cursor=0&pageSize=10
Authorization: Bearer {{accessToken}}

### 배너 상세 조회
@bannerId = 1
GET {{host}}/banners/{{bannerId}}
Authorization: Bearer {{accessToken}}

### 배너 생성
POST {{host}}/banners
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
"name": "새 배너",
"nameFontColor": "#ffffff",
"descriptionA": "배너 설명A",
"descriptionB": "배너 설명B",
"descriptionFontColor": "#ffffff",
"imageUrl": "https://example.com/banner.jpg",
"textPosition": "RT",
"isExternalUrl": false,
"targetUrl": "https://www.instagram.com/bottle_note_official",
"bannerType": "CURATION",
"sortOrder": 0,
"startDate": "2026-02-11T00:00:00",
"endDate": "2026-02-12T00:00:00"
}

### 배너 수정
@bannerId = 1
PUT {{host}}/banners/{{bannerId}}
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
"name": "수정된 배너",
"nameFontColor": "#000000",
"descriptionA": "수정된 설명A",
"descriptionB": "수정된 설명B",
"descriptionFontColor": "#000000",
"imageUrl": "https://example.com/banner-updated.jpg",
"textPosition": "RT",
"isExternalUrl": false,
"targetUrl": "https://www.instagram.com/bottle_note_official",
"bannerType": "CURATION",
"sortOrder": 1,
"startDate": "2026-02-11T00:00:00",
"endDate": "2026-02-28T00:00:00",
"isActive": true
}

### 배너 삭제
@bannerId = 1
DELETE {{host}}/banners/{{bannerId}}
Authorization: Bearer {{accessToken}}

### 배너 활성화 상태 변경
@bannerId = 1
PATCH {{host}}/banners/{{bannerId}}/status
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
"isActive": true
}

### 배너 정렬 순서 변경
@bannerId = 1
PATCH {{host}}/banners/{{bannerId}}/sort-order
Authorization: Bearer {{accessToken}}
Content-Type: application/json

{
"sortOrder": 0
}
Loading