Skip to content

Commit

Permalink
v0.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
youlalala committed Nov 23, 2023
2 parents 3a54502 + e8828ac commit 1087d23
Show file tree
Hide file tree
Showing 127 changed files with 2,791 additions and 317 deletions.
12 changes: 10 additions & 2 deletions .github/workflows/android-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,20 @@ jobs:
uses: actions/upload-artifact@v3
with:
name: release-artifacts
path: ./android/app/build/outputs/apk/release/
path: android/app/build/outputs/apk/release/
if-no-files-found: error

- name: Create Github Release
uses: softprops/action-gh-release@v1
with:
generate_release_notes: true
files: |
./android/app/build/outputs/apk/release/*.apk
android/app/build/outputs/apk/release/app-release.apk
- name: Upload artifact to Firebase App Distribution
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{secrets.FIREBASE_APP_ID}}
serviceCredentialsFileContent: ${{ secrets.CREDENTIAL_FILE_CONTENT }}
groups: testers
file: android/app/build/outputs/apk/release/app-release.apk
4 changes: 2 additions & 2 deletions .github/workflows/android-pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ jobs:
KEYSTORE_PROPERTIES: ${{ secrets.KEYSTORE_PROPERTIES }}
LOCAL_PROPERTIES: ${{ secrets.LOCAL_PROPERTIES }}
run: |
echo "$DEBUG_KEYSTORE" | base64 -d > keystore.properties
echo "$DEBUG_KEYSTORE" | base64 -d > debug.keystore
echo "$KEYSTORE_PROPERTIES" > keystore.properties
echo "$LOCAL_PROPERTIES" > local.properties
./gradlew testDebugUnitTest --stacktrace
./gradlew debugUnitTest --stacktrace
- name: Publish Test Results
if: always()
Expand Down
79 changes: 79 additions & 0 deletions .github/workflows/server-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Server CD

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

jobs:
deploy:
runs-on: ubuntu-20.04

strategy:
matrix:
node-version: [20.x]

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'

- name: Install depenencies
run: |
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 }}
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
- name: Build Docker image
run: docker build --platform linux/amd64 ./server -t ${{ secrets.NCP_REGISTRY }}/catchy-tape:latest

- name: Login NCP container registry
run: docker login ${{ secrets.NCP_REGISTRY }} -u ${{ secrets.NCP_DOCKER_ACCESS_KEY_ID }} -p ${{ secrets.NCP_DOCKER_SECRET_KEY }}

- name: Push Docker image to registry
run: docker push ${{ secrets.NCP_REGISTRY }}/catchy-tape:latest

- 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 }}
38 changes: 38 additions & 0 deletions .github/workflows/server-dev-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Backend Dev CI

on:
pull_request:
branches: [develop]
paths:
- "server/**"

defaults:
run:
working-directory: ./server

jobs:
BACKEND-CI:
runs-on: ubuntu-20.04

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

- name: Use NodeJS
uses: actions/setup-node@v2
with:
node-version: 20.8.1

- name: Cache node modules
id: cache
uses: actions/cache@v2
with:
path: "**/node_modules"
key: npm-packages-${{ hashFiles('**/package-lock.json') }}

- name: Install Dependency
if: steps.cache.outputs.cache-hit != 'true'
run: npm install

- name: Execute Test
run: npm run test
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@
### 🤖 Android
| Category | TechStack | 기록 |
| ------------- | ------------- | ------------- |
| Architecture | Clean Architecture, Multi Module, MVVM | [프로젝트 구조](https://tral-lalala.tistory.com/126)
| Architecture | Clean Architecture, Multi Module, MVVM | [프로젝트 구조](https://tral-lalala.tistory.com/126)[build-logic](https://algosketch.tistory.com/179)
| DI | Hilt |
| Network | Retrofit, Kotlin Serialization | [역/직렬화 라이브러리 비교](https://github.com/boostcampwm2023/and04-catchy-tape/wiki/%EC%97%AD-%EC%A7%81%EB%A0%AC%ED%99%94-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EB%B9%84%EA%B5%90)
| Jetpack | Navigation |
| CI | Github Actions | [PR에 대한 단위 테스트 자동화](https://algosketch.tistory.com/178)
<details>
| Asynchronous | Coroutines, Flow
| Jetpack | DataBinding, Navigation |
| CI/CD | Github Actions |[PR 단위 테스트 자동화](https://algosketch.tistory.com/178)[Github Release 자동화](https://tral-lalala.tistory.com/127)[Firebase App 배포 자동화](https://tral-lalala.tistory.com/128)
| Test | Kotest

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

- [프로젝트 생성](https://github.com/boostcampwm2023/and04-catchy-tape/wiki/Android#%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1%EC%8B%9C-%EA%B3%A0%EB%A0%A4%ED%95%9C-%EB%82%B4%EC%9A%A9)
Expand Down
3 changes: 2 additions & 1 deletion android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ android {
minSdk = 26
targetSdk = 33
versionCode = 1
versionName = "1.0.0"
versionName = "0.1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down Expand Up @@ -63,6 +63,7 @@ dependencies {
implementation(project(":feature:home"))
implementation(project(":feature:login"))
implementation(project(":feature:upload"))
implementation(project(":feature:player"))
implementation(project(":core:data"))

implementation(libs.core.ktx)
Expand Down
11 changes: 10 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

<application
Expand All @@ -12,14 +13,22 @@
android:usesCleartextTraffic="true"
android:theme="@style/Theme.CatchyTape">
<activity
android:name=".MainActivity"
android:name=".feature.login.LoginActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>


<activity
android:name=".MainActivity"
android:exported="true">
</activity>


</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ class CtApplication : Application() {
super.onCreate()
if (BuildConfig.DEBUG) {
Timber.plant(object : Timber.DebugTree() {
override fun d(message: String?, vararg args: Any?) {
if (message != null && message.isEmpty()) {
super.d(getString(R.string.timber_blank_string), *args)
} else {
super.d(message, *args)
}
}

override fun createStackElementTag(element: StackTraceElement): String {
return String.format(
getString(R.string.timber_log_format),
Expand Down
28 changes: 22 additions & 6 deletions android/app/src/main/java/com/ohdodok/catchytape/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
package com.ohdodok.catchytape

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.net.ConnectivityManager
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.os.Bundle
import com.ohdodok.catchytape.feature.login.LoginActivity
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import dagger.hilt.android.AndroidEntryPoint
import com.ohdodok.catchytape.core.ui.R.string as uiString

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
private lateinit var connectivityManager: ConnectivityManager

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// TODO : 자동로그인 할 때 수정 필요
val intent = Intent(this, LoginActivity::class.java)
startActivity(intent)
connectivityManager = getSystemService(ConnectivityManager::class.java)
checkNetworkState()

val networkStateObserver = NetworkStateObserver(connectivityManager, ::checkNetworkState)
lifecycle.addObserver(networkStateObserver)
}

private fun checkNetworkState() {
val activeNetwork = connectivityManager.activeNetwork
val capabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
val isNetworkAvailable = capabilities?.hasCapability(NET_CAPABILITY_VALIDATED) ?: false

if (!isNetworkAvailable) {
Toast.makeText(this, getString(uiString.check_network), Toast.LENGTH_LONG).show()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.ohdodok.catchytape

import android.net.ConnectivityManager
import android.net.Network
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner

class NetworkStateObserver(
private val connectivityManager: ConnectivityManager,
checkNetworkState: () -> Unit
) : DefaultLifecycleObserver {

private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onLost(network: Network) {
super.onLost(network)
checkNetworkState()
}
}

override fun onResume(owner: LifecycleOwner) {
super.onResume(owner)
connectivityManager.registerDefaultNetworkCallback(networkCallback)
}

override fun onPause(owner: LifecycleOwner) {
super.onPause(owner)
connectivityManager.unregisterNetworkCallback(networkCallback)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
<include app:graph="@navigation/home_navigation" />
<include app:graph="@navigation/login_navigation" />
<include app:graph="@navigation/upload_navigation" />
<include app:graph="@navigation/player_navigation" />

</navigation>
1 change: 1 addition & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<resources>
<string name="app_name">Catchy Tape</string>
<string name="timber_log_format">C: %s, L: %s</string>
<string name="timber_blank_string">"BLANK("")"</string>
</resources>
13 changes: 13 additions & 0 deletions android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,17 @@ plugins {
alias(libs.plugins.kotlinx.serialization) apply false
alias(libs.plugins.navigation.safe.args) apply false
}


tasks.register<Exec>("domainUnitTest") {
commandLine = listOf("gradle", "core:domain:test")
}


tasks.register<Exec>("debugUnitTest") {
dependsOn("domainUnitTest")
commandLine = listOf("gradle", "testDebugUnitTest")
}


true // Needed to make the Suppress annotation work for the plugins block
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.ohdodok.catchytape.core.data.api

import com.ohdodok.catchytape.core.data.model.MusicGenresResponse
import com.ohdodok.catchytape.core.data.model.MusicRequest
import com.ohdodok.catchytape.core.data.model.MusicResponse
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST

interface MusicApi {

@GET("musics/genres")
suspend fun getGenres(): Response<MusicGenresResponse>

@POST("musics")
suspend fun postMusic(
@Body music: MusicRequest
): Response<Unit>

@GET("musics/recent-uploads")
suspend fun getRecentUploads(): Response<List<MusicResponse>>

}
Loading

0 comments on commit 1087d23

Please sign in to comment.