Skip to content

Commit

Permalink
v0.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
youlalala committed Dec 7, 2023
2 parents 62f5ec4 + f6402d0 commit b33a432
Show file tree
Hide file tree
Showing 138 changed files with 3,261 additions and 555 deletions.
84 changes: 47 additions & 37 deletions .github/workflows/server-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ name: Server CD

on:
pull_request:
branches: [ "develop", "main" ]
branches: ["develop", "main"]
paths:
- "server/**"
types:
- closed

jobs:
deploy:
runs-on: ubuntu-20.04
Expand All @@ -19,40 +19,50 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
cache-dependency-path: '**/package-lock.json'
cache: "npm"
cache-dependency-path: "**/package-lock.json"

- name: Install depenencies
run: |
cd server
npm install
cd server
npm install
- name: Create prod.env file
env:
DB_HOST_IP: ${{ secrets.SERVER_ENV_DB_HOST_IP }}
DB_PORT: ${{ secrets.SERVER_ENV_DB_PORT }}
DB_USER_NAME: ${{ secrets.SERVER_ENV_DB_USER_NAME }}
DB_PASSWORD: ${{ secrets.SERVER_ENV_DB_PASSWORD }}
DB_DATABASE_NAME: ${{ secrets.SERVER_ENV_DB_DATABASE_NAME }}
ACCESS_ID: ${{ secrets.SERVER_ENV_ACCESS_ID }}
SECRET_ACCESS_KEY: ${{ secrets.SERVER_ENV_SECRET_ACCESS_KEY }}
JWT_SECRET_KEY: ${{ secrets.SERVER_ENV_JWT_SECRET_KEY }}
DB_HOST_IP: ${{ secrets.SERVER_ENV_DB_HOST_IP }}
DB_PORT: ${{ secrets.SERVER_ENV_DB_PORT }}
DB_USER_NAME: ${{ secrets.SERVER_ENV_DB_USER_NAME }}
DB_PASSWORD: ${{ secrets.SERVER_ENV_DB_PASSWORD }}
DB_DATABASE_NAME: ${{ secrets.SERVER_ENV_DB_DATABASE_NAME }}
ACCESS_ID: ${{ secrets.SERVER_ENV_ACCESS_ID }}
SECRET_ACCESS_KEY: ${{ secrets.SERVER_ENV_SECRET_ACCESS_KEY }}
JWT_SECRET_KEY: ${{ secrets.SERVER_ENV_JWT_SECRET_KEY }}
GREEN_EYE_SECRET_KEY: ${{secrets.GREEN_EYE_SECRET_KEY}}
GREEN_EYE_REQUEST_URL: ${{secrets.GREEN_EYE_REQUEST_URL}}
CLOUD_FUNCTIONS_EXECUTE_URL: ${{secrets.CLOUD_FUNCTIONS_EXECUTE_URL}}
CLOUD_FUNCTIONS_REQUEST_URL: ${{secrets.CLOUD_FUNCTIONS_REQUEST_URL}}
API_GW_ACCESS_KEY: ${{secrets.API_GW_ACCESS_KEY}}
run: |
cd server
touch prod.env
echo "DB_HOST_IP=$DB_HOST_IP" >> prod.env
echo "DB_PORT=$DB_PORT" >> prod.env
echo "DB_USER_NAME=$DB_USER_NAME" >> prod.env
echo "DB_PASSWORD=$DB_PASSWORD" >> prod.env
echo "DB_DATABASE_NAME=$DB_DATABASE_NAME" >> prod.env
echo "ACCESS_ID=$ACCESS_ID" >> prod.env
echo "SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY" >> prod.env
echo "JWT_SECRET_KEY=$JWT_SECRET_KEY" >> prod.env
cd server
touch prod.env
echo "DB_HOST_IP=$DB_HOST_IP" >> prod.env
echo "DB_PORT=$DB_PORT" >> prod.env
echo "DB_USER_NAME=$DB_USER_NAME" >> prod.env
echo "DB_PASSWORD=$DB_PASSWORD" >> prod.env
echo "DB_DATABASE_NAME=$DB_DATABASE_NAME" >> prod.env
echo "ACCESS_ID=$ACCESS_ID" >> prod.env
echo "SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY" >> prod.env
echo "JWT_SECRET_KEY=$JWT_SECRET_KEY" >> prod.env
echo "GREEN_EYE_SECRET_KEY=$GREEN_EYE_SECRET_KEY" >> prod.env
echo "GREEN_EYE_REQUEST_URL=$GREEN_EYE_REQUEST_URL" >> prod.env
echo "CLOUD_FUNCTIONS_EXECUTE_URL=$CLOUD_FUNCTIONS_EXECUTE_URL" >> prod.env
echo "CLOUD_FUNCTIONS_REQUEST_URL=$CLOUD_FUNCTIONS_REQUEST_URL" >> prod.env
echo "API_GW_ACCESS_KEY=$API_GW_ACCESS_KEY" >> prod.env
- name: Build Docker image
run: docker build --platform linux/amd64 ./server -t ${{ secrets.NCP_REGISTRY }}/catchy-tape:latest
Expand All @@ -66,14 +76,14 @@ jobs:
- name: SSH into Server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_SSH_HOST }}
username: ${{ secrets.SERVER_SSH_USER }}
password: ${{ secrets.SERVER_SSH_PASSWORD }}
port: ${{ secrets.SERVER_SSH_PORT }}
script: |
docker login ${{ secrets.NCP_REGISTRY }} -u ${{ secrets.NCP_DOCKER_ACCESS_KEY_ID }} -p ${{ secrets.NCP_DOCKER_SECRET_KEY }}
docker pull ${{ secrets.NCP_REGISTRY }}/catchy-tape:latest
docker stop catchy-tape-latest
docker rm catchy-tape-latest
docker run -d -p 3000:3000 --name catchy-tape-latest ${{ secrets.NCP_REGISTRY }}/catchy-tape:latest
curl -X POST -H 'Content-type: application/json' --data '{"text":"서버 배포 성공!"}' ${{ secrets.SLACK_WEBHOOK_URL }}
host: ${{ secrets.SERVER_SSH_HOST }}
username: ${{ secrets.SERVER_SSH_USER }}
password: ${{ secrets.SERVER_SSH_PASSWORD }}
port: ${{ secrets.SERVER_SSH_PORT }}
script: |
docker login ${{ secrets.NCP_REGISTRY }} -u ${{ secrets.NCP_DOCKER_ACCESS_KEY_ID }} -p ${{ secrets.NCP_DOCKER_SECRET_KEY }}
docker pull ${{ secrets.NCP_REGISTRY }}/catchy-tape:latest
docker stop catchy-tape-latest
docker rm catchy-tape-latest
docker run -d -p 3000:3000 --name catchy-tape-latest ${{ secrets.NCP_REGISTRY }}/catchy-tape:latest
curl -X POST -H 'Content-type: application/json' --data '{"text":"서버 배포 성공!"}' ${{ secrets.SLACK_WEBHOOK_URL }}
31 changes: 31 additions & 0 deletions .github/workflows/server-dev-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,36 @@ jobs:
if: steps.cache.outputs.cache-hit != 'true'
run: npm install

- name: Create dev.env file
env:
DB_HOST_IP: ${{ secrets.SERVER_DEV_DB_HOST_IP }}
DB_PORT: ${{ secrets.SERVER_DEV_DB_PORT }}
DB_USER_NAME: ${{ secrets.SERVER_DEV_DB_USER_NAME }}
DB_PASSWORD: ${{ secrets.SERVER_DEV_DB_PASSWORD }}
DB_DATABASE_NAME: ${{ secrets.SERVER_DEV_DB_DATABASE_NAME }}
ACCESS_ID: ${{ secrets.SERVER_ENV_ACCESS_ID }}
SECRET_ACCESS_KEY: ${{ secrets.SERVER_ENV_SECRET_ACCESS_KEY }}
JWT_SECRET_KEY: ${{ secrets.SERVER_ENV_JWT_SECRET_KEY }}
GREEN_EYE_SECRET_KEY: ${{secrets.GREEN_EYE_SECRET_KEY}}
GREEN_EYE_REQUEST_URL: ${{secrets.GREEN_EYE_REQUEST_URL}}
CLOUD_FUNCTIONS_EXECUTE_URL: ${{secrets.CLOUD_FUNCTIONS_EXECUTE_URL}}
CLOUD_FUNCTIONS_REQUEST_URL: ${{secrets.CLOUD_FUNCTIONS_REQUEST_URL}}
API_GW_ACCESS_KEY: ${{secrets.API_GW_ACCESS_KEY}}
run: |
touch dev.env
echo "DB_HOST_IP=$DB_HOST_IP" >> dev.env
echo "DB_PORT=$DB_PORT" >> dev.env
echo "DB_USER_NAME=$DB_USER_NAME" >> dev.env
echo "DB_PASSWORD=$DB_PASSWORD" >> dev.env
echo "DB_DATABASE_NAME=$DB_DATABASE_NAME" >> dev.env
echo "ACCESS_ID=$ACCESS_ID" >> dev.env
echo "SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY" >> dev.env
echo "JWT_SECRET_KEY=$JWT_SECRET_KEY" >> dev.env
echo "GREEN_EYE_SECRET_KEY=$GREEN_EYE_SECRET_KEY" >> dev.env
echo "GREEN_EYE_REQUEST_URL=$GREEN_EYE_REQUEST_URL" >> dev.env
echo "CLOUD_FUNCTIONS_EXECUTE_URL" >> dev.env
echo "CLOUD_FUNCTIONS_REQUEST_URL" >> dev.env
echo "API_GW_ACCESS_KEY" >> dev.env
- name: Execute Test
run: npm run test
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,14 @@
### 📡 Server
| Category | TechStack |
| ------------- | ------------- |
| | |
| Framework, Language | NestJS, TypeScript |
| DB | MySQL |
| ORM | TypeORM |
| Test | Jest |
| API Docs | SwaggerHub |
| CI/CD | Github Actions |
| NCP | Server, Container Registry, VPC, Object Storage|

<details>
<summary>그 외 기록</summary>

Expand Down
6 changes: 4 additions & 2 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ android {
applicationId = "com.ohdodok.catchytape"
minSdk = 26
targetSdk = 33
versionCode = 2
versionName = "0.2.0"
versionCode = 3
versionName = "0.3.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down Expand Up @@ -66,7 +66,9 @@ dependencies {
implementation(project(":feature:player"))
implementation(project(":feature:playlist"))
implementation(project(":feature:mypage"))
implementation(project(":feature:search"))
implementation(project(":core:data"))
implementation(project(":core:domain"))

implementation(libs.core.ktx)
implementation(libs.appcompat)
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
android:exported="true" />

<service
android:name=".mediacontrol.PlaybackService"
android:name=".mediasession.PlaybackService"
android:exported="true"
android:foregroundServiceType="mediaPlayback">
<intent-filter>
Expand Down
60 changes: 56 additions & 4 deletions android/app/src/main/java/com/ohdodok/catchytape/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ohdodok.catchytape

import android.animation.ObjectAnimator
import android.content.ComponentName
import android.net.ConnectivityManager
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
Expand All @@ -8,6 +9,8 @@ import android.view.View
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.animation.doOnEnd
import androidx.core.view.WindowCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
Expand All @@ -19,17 +22,25 @@ import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
import com.ohdodok.catchytape.databinding.ActivityMainBinding
import com.ohdodok.catchytape.feature.player.PlayerEvent
import com.ohdodok.catchytape.feature.player.PlayerListener
import com.ohdodok.catchytape.feature.player.PlayerViewModel
import com.ohdodok.catchytape.mediacontrol.PlaybackService
import com.ohdodok.catchytape.feature.player.getMediasWithMetaData
import com.ohdodok.catchytape.feature.player.millisecondsPerSecond
import com.ohdodok.catchytape.feature.player.moveNextMedia
import com.ohdodok.catchytape.feature.player.navigateToPlayer
import com.ohdodok.catchytape.feature.player.onPreviousBtnClick
import com.ohdodok.catchytape.mediasession.PlaybackService
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.launch
import javax.inject.Inject
import com.ohdodok.catchytape.core.ui.R.string as uiString

private const val BOTTOM_NAV_ANIMATION_DURATION = 700L

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

Expand All @@ -39,14 +50,16 @@ class MainActivity : AppCompatActivity() {
private lateinit var connectivityManager: ConnectivityManager
private val playViewModel: PlayerViewModel by viewModels()


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

binding.viewModel = playViewModel
binding.lifecycleOwner = this

WindowCompat.setDecorFitsSystemWindows(window, false)

setupBottomNav()
setUpPlayerController()
connectivityManager = getSystemService(ConnectivityManager::class.java)
Expand All @@ -57,6 +70,9 @@ class MainActivity : AppCompatActivity() {

setupPlayer()
setupPlayButton()
setupPreviousButton()
setupNextButton()
observePlaylistChange()
}

override fun onStart() {
Expand Down Expand Up @@ -106,11 +122,20 @@ class MainActivity : AppCompatActivity() {
}

private fun hideBottomNav() {
binding.bottomNav.visibility = View.GONE
val height = binding.bottomNav.height.toFloat()
ObjectAnimator.ofFloat(binding.bottomNav, "translationY", height).apply {
duration = BOTTOM_NAV_ANIMATION_DURATION
doOnEnd { binding.bottomNav.visibility = View.GONE }
start()
}
}

private fun showBottomNav() {
binding.bottomNav.visibility = View.VISIBLE
ObjectAnimator.ofFloat(binding.bottomNav, "translationY", 0f).apply {
duration = BOTTOM_NAV_ANIMATION_DURATION
start()
}
}

private fun hidePlayerController() {
Expand All @@ -121,7 +146,6 @@ class MainActivity : AppCompatActivity() {
binding.pcvController.visibility = View.VISIBLE
}


private fun setupPlayer() {
player.addListener(PlayerListener(playViewModel))
player.prepare()
Expand All @@ -142,11 +166,39 @@ class MainActivity : AppCompatActivity() {
}
}

private fun observePlaylistChange() {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
playViewModel.events
.filterIsInstance<PlayerEvent.PlaylistChanged>()
.collectLatest { event ->
val newItems = getMediasWithMetaData(event.currentPlaylist.musics)
player.clearMediaItems()
player.setMediaItems(newItems)

player.seekTo(event.currentPlaylist.startMusicIndex, 0)
player.play()
}
}
}
}

private fun setupPlayButton() {
binding.pcvController.setOnPlayButtonClick {
if (playViewModel.uiState.value.isPlaying) player.pause()
else player.play()
}
}

private fun setupPreviousButton() {
binding.pcvController.setOnPreviousButtonClick {
player.onPreviousBtnClick()
}
}

private fun setupNextButton() {
binding.pcvController.setOnNextButtonClick {
player.moveNextMedia()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ohdodok.catchytape.mediacontrol
package com.ohdodok.catchytape.mediasession

import android.content.Intent
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService
Expand All @@ -26,6 +27,11 @@ class PlaybackService : MediaSessionService() {
super.onDestroy()
}

override fun onTaskRemoved(rootIntent: Intent?) {
player.pause()
stopSelf()
}

override fun onGetSession(
controllerInfo: MediaSession.ControllerInfo
): MediaSession? = mediaSession
Expand Down
13 changes: 13 additions & 0 deletions android/app/src/main/res/drawable/ic_search.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M21,21L15,15M3,10C3,10.919 3.181,11.83 3.533,12.679C3.885,13.528 4.4,14.3 5.05,14.95C5.7,15.6 6.472,16.115 7.321,16.467C8.17,16.819 9.081,17 10,17C10.919,17 11.83,16.819 12.679,16.467C13.528,16.115 14.3,15.6 14.95,14.95C15.6,14.3 16.115,13.528 16.467,12.679C16.819,11.83 17,10.919 17,10C17,9.081 16.819,8.17 16.467,7.321C16.115,6.472 15.6,5.7 14.95,5.05C14.3,4.4 13.528,3.885 12.679,3.533C11.83,3.181 10.919,3 10,3C9.081,3 8.17,3.181 7.321,3.533C6.472,3.885 5.7,4.4 5.05,5.05C4.4,5.7 3.885,6.472 3.533,7.321C3.181,8.17 3,9.081 3,10Z"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="@color/on_surface"
android:strokeLineCap="round"/>
</vector>
Loading

0 comments on commit b33a432

Please sign in to comment.