NodeJS ile InnerLoop Geliştirme

1. Genel Bakış

Bu laboratuvarda, container mimarisine alınmış bir ortamda NodeJS uygulamaları geliştirmekle görevli yazılım mühendislerinin geliştirme iş akışını kolaylaştırmak için tasarlanmış özellikler ve işlevler gösterilmektedir. Tipik container geliştirme sürecinde kullanıcının container'larla ve container derleme işlemiyle ilgili ayrıntıları anlaması gerekir. Ayrıca geliştiriciler, uygulamalarını uzak ortamlarda test edip hata ayıklama yapmak için genellikle akışlarını kesip IDE'lerinden çıkmak zorunda kalırlar. Bu eğitimde bahsedilen araçlar ve teknolojiler sayesinde geliştiriciler, IDE'lerinden ayrılmadan kapsayıcılı uygulamalarla etkili bir şekilde çalışabilir.

Öğrenecekleriniz

Bu laboratuvarda, GCP'de kapsayıcılarla geliştirme yöntemlerini öğreneceksiniz. Bu yöntemler arasında şunlar yer alır:

  • Başlangıç Node.js uygulaması oluşturma
  • Node.js uygulamasını kapsayıcı geliştirme için yapılandırma
  • Basit bir CRUD Rest Hizmeti kodlama
  • GKE'ye dağıtma
  • Hata durumunu ayıklama
  • Kesme noktası / günlükleri kullanma
  • Değişiklikleri GKE'ye hızlı dağıtma
  • İsteğe bağlı: Arka uçta kalıcılık için Cloud SQL'i entegre etme

2. Kurulum ve Gereksinimler

Yönlendirmesiz ortam kurulumu

  1. Google Cloud Console'da oturum açın ve yeni bir proje oluşturun veya mevcut bir projeyi yeniden kullanın. Gmail veya Google Workspace hesabınız yoksa hesap oluşturmanız gerekir.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Proje adı, bu projenin katılımcıları için görünen addır. Google API'leri tarafından kullanılmayan bir karakter dizisidir ve istediğiniz zaman güncelleyebilirsiniz.
  • Proje kimliği, tüm Google Cloud projelerinde benzersiz olmalı ve sabittir (ayarlandıktan sonra değiştirilemez). Cloud Console, benzersiz bir dizeyi otomatik olarak oluşturur. Genellikle bu dizenin ne olduğuyla ilgilenmezsiniz. Çoğu codelab'de proje kimliğine (genellikle PROJECT_ID olarak tanımlanır) başvurmanız gerekir. Bu nedenle, proje kimliğini beğenmezseniz başka bir rastgele kimlik oluşturabilir veya kendi kimliğinizi deneyip kullanılabilir olup olmadığını görebilirsiniz. Proje oluşturulduktan sonra bu değer "dondurulur".
  • Bazı API'lerin kullandığı üçüncü bir değer olan Proje Numarası da vardır. Bu üç değer hakkında daha fazla bilgiyi belgelerde bulabilirsiniz.
  1. Ardından, Cloud kaynaklarını/API'lerini kullanmak için Cloud Console'da faturalandırmayı etkinleştirmeniz gerekir. Bu codelab'i tamamlamak neredeyse hiç maliyetli değildir. Bu eğitimin ötesinde faturalandırma ücreti alınmaması için kaynakları kapatmak üzere codelab'in sonunda bulunan "temizleme" talimatlarını uygulayın. Google Cloud'un yeni kullanıcıları 300 ABD doları değerinde ücretsiz deneme programından yararlanabilir.

Cloud Shell Düzenleyici'yi başlatma

Bu laboratuvar, Google Cloud Shell Düzenleyici ile kullanılmak üzere tasarlanmış ve test edilmiştir. Düzenleyiciye erişmek için:

  1. https://console.cloud.google.com adresinden Google projenize erişin.
  2. Sağ üst köşedeki Cloud Shell düzenleyici simgesini tıklayın.

8560cc8d45e8c112.png

  1. Pencerenizin alt kısmında yeni bir bölme açılır.
  2. Open Editor (Düzenleyiciyi Aç) düğmesini tıklayın.

9e504cb98a6a8005.png

  1. Düzenleyici, sağda bir gezgin ve merkezi alanda bir düzenleyiciyle açılır.
  2. Ekranın alt kısmında bir terminal bölmesi de bulunmalıdır.
  3. Terminal açık DEĞİLSE yeni bir terminal penceresi açmak için `ctrl+`` tuş kombinasyonunu kullanın.

gcloud'u ayarlama

Cloud Shell'de proje kimliğinizi ve uygulamanızı dağıtmak istediğiniz bölgeyi ayarlayın. Bunları PROJECT_ID ve REGION değişkenleri olarak kaydedin.

export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')

GKE kümesi ve veritabanı oluşturma

  1. Kurulum komut dosyasını indirip yürütülebilir hale getirin.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/setup.sh
chmod +x setup.sh

Bu laboratuvarda kullanılan altyapıyı sağlama

Bu laboratuvarda, GKE'ye kod dağıtacak ve Spanner veritabanında depolanan verilere erişeceksiniz. Aşağıdaki kurulum komut dosyası bu altyapıyı sizin için hazırlar.

  1. setup.sh dosyasını açın ve şu anda CHANGEME olarak ayarlanmış şifrelerin değerlerini düzenleyin.
  2. Bu laboratuvarda kullanacağınız bir GKE kümesi ve Cloud SQL veritabanı oluşturmak için kurulum komut dosyasını çalıştırın.
./setup.sh
  1. Cloud Shell'de mynodejsapp adlı yeni bir dizin oluşturun.
mkdir mynodejsapp
  1. Bu dizine geçin ve dizini çalışma alanı olarak açın. Bu işlem, yeni oluşturulan klasörde bir çalışma alanı yapılandırması oluşturarak düzenleyiciyi yeniden yükler.
cd mynodejsapp && cloudshell workspace .
  1. NVM'yi kullanarak Node ve NPM'yi yükleyin.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
        
        # This loads nvm bash_completion
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  

nvm install stable

nvm alias default stable

3. Yeni bir başlangıç uygulaması oluşturma

  1. Uygulamayı başlatma

Aşağıdaki komutu çalıştırarak package.json dosyası oluşturma

npm init
    Choose the entry point: (index.js) src/index.js and default values for the rest of the parameters. This will create the file with following contents
{
  "name": "mynodejsapp",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
  1. Giriş noktası ekleme

Bu dosyayı, komut dosyasına başlatma komutunu ekleyecek şekilde düzenleyin "start": "node src/index.js",. Değişiklikten sonra komut dosyaları aşağıdaki kod snippet'ine benzemelidir:

"scripts": {
    "start": "node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  1. Express bağımlılığını ekleme

Ekleyeceğimiz kod da express kullandığı için bu bağımlılığı package.json dosyasına ekleyelim. Bu nedenle, tüm değişikliklerden sonra package.json dosyası aşağıdaki gibi olmalıdır.

​​{
  "name": "mynodejsapp",
  "version": "1.0.0",
  "description": "",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Your Name",
  "license": "ISC",
  "dependencies": {
    "express": "^4.16.4"
  }
}
  1. index.js dosyasını oluşturma

src adlı bir kaynak dizini oluşturun

Aşağıdaki kodu kullanarak src/index.js dosyasını oluşturun.

const express = require('express');
const app = express();
const PORT = 8080;

app.get('/', (req, res) => {
    var message="Greetings from Node";
    res.send({ message: message });
  });

app.listen(PORT, () => {
  console.log(`Server running at: http://localhost:${PORT}/`);

});

PORT'un 8080 değerine ayarlandığını unutmayın.

Manifest Dosyaları Oluşturma

Skaffold, container geliştirmeyi basitleştirmek için entegre araçlar sunar. Bu adımda, temel Kubernetes YAML dosyalarını otomatik olarak oluşturacak olan Skaffold'u başlatacaksınız. İşlemi başlatmak için aşağıdaki komutu yürütün.

Terminalde aşağıdaki komutu çalıştırın.

skaffold init --generate-manifests

İstendiğinde:

  • Bağlantı noktası olarak 8080 girin.
  • Yapılandırmayı kaydetmek için y girin.

Çalışma alanına skaffold.yaml ve deployment.yaml olmak üzere iki dosya eklenir.

Uygulama adını güncelleme

Yapılandırmaya dahil edilen varsayılan değerler şu anda uygulamanızın adıyla eşleşmiyor. Dosyaları, varsayılan değerler yerine uygulama adınıza referans verecek şekilde güncelleyin.

  1. Skaffold yapılandırmasındaki girişleri değiştirme
  • skaffold.yaml uygulamasını aç
  • Şu anda package-json-image olarak ayarlanmış resim adını seçin.
  • Sağ tıklayın ve Tüm Oluşumları Değiştir'i seçin.
  • Yeni adı mynodejsapp olarak yazın.
  1. Kubernetes yapılandırmasındaki girişleri değiştirme
  • deployment.yaml dosyasını aç
  • Şu anda package-json-image olarak ayarlanmış resim adını seçin.
  • Sağ tıklayın ve Tüm Oluşumları Değiştir'i seçin.
  • Yeni adı mynodejsapp olarak yazın.

skaffold.yaml dosyasındaki build bölümünde, uygulamayı kapsüllemek için buildpacks kullanıldığını unutmayın. Bu kodda Dockerfile yok ve geliştiricinin bu uygulamayı kapsayıcılaştırmak için Docker bilgisine ihtiyacı yok.

Ayrıca, bu skaffold yapılandırmasıyla düzenleyici ve çalışan kapsayıcı arasında otomatik olarak hızlı senkronizasyon etkinleştirilir. Anında senkronizasyonu etkinleştirmek için ek yapılandırma gerekmez.

4. Geliştirme sürecini inceleme

Bu bölümde, temel süreçleri öğrenmek ve başlangıç uygulamanızın yapılandırmasını ve kurulumunu doğrulamak için Cloud Code eklentisini kullanarak birkaç adımı inceleyeceksiniz.

Cloud Code, geliştirme sürecinizi kolaylaştırmak için skaffold ile entegre olur. Aşağıdaki adımlarda GKE'ye dağıtım yaptığınızda Cloud Code ve Skaffold, container görüntünüzü otomatik olarak oluşturur, Container Registry'ye aktarır ve ardından uygulamanızı GKE'ye dağıtır. Bu işlem, geliştirici akışından ayrıntıları soyutlayarak arka planda gerçekleşir. Cloud Code, kapsayıcı tabanlı geliştirmeye geleneksel hata ayıklama ve anında senkronizasyon özellikleri sunarak geliştirme sürecinizi de iyileştirir.

Kubernetes'e dağıtma

  1. Cloud Shell Düzenleyici'nin alt kısmındaki bölmede Cloud Code'u seçin. 

fdc797a769040839.png

  1. En üstte görünen panelde Kubernetes'te çalıştır'ı seçin. İstenirse mevcut Kubernetes bağlamını kullanmak için Evet'i seçin.

cfce0d11ef307087.png

  1. Komutu ilk kez çalıştırdığınızda ekranın üst kısmında, mevcut Kubernetes bağlamını kullanmak isteyip istemediğinizi soran bir istem görünür. Kabul etmek ve mevcut bağlamı kullanmak için "Evet"i seçin.

817ee33b5b412ff8.png

  1. Ardından, hangi Container Registry'nin kullanılacağını soran bir istem gösterilir. Sağlanan varsayılan değeri kabul etmek için Enter tuşuna basın.

eb4469aed97a25f6.png

  1. İlerleme durumunu ve bildirimleri görüntülemek için alt bölmede Çıkış sekmesini seçin.

f95b620569ba96c5.png

  1. Ek ayrıntıları ve kapsayıcılardan canlı olarak yayınlanan günlükleri görüntülemek için sağdaki kanal açılır listesinde "Kubernetes: Run/Debug - Detailed"ı seçin.

94acdcdda6d2108.png

  1. Açılır listeden "Kubernetes: Run/Debug" (Kubernetes: Çalıştır/Hata Ayıkla) seçeneğini belirleyerek basitleştirilmiş görünüme dönün.
  2. Derleme ve testler tamamlandığında Çıkış sekmesinde Resource deployment/mynodejsapp status completed successfully ifadesi gösterilir ve "Forwarded URL from service demo-app: http://localhost:8080" URL'si listelenir.
  3. Cloud Code terminalinde, çıkıştaki URL'nin (http://localhost:8080) üzerine gelin ve ardından görüntülenen araç ipucunda Open Web Preview'u (Web Önizlemesini Aç) seçin.

Yanıt şöyle olur:

{"message":"Greetings from Node"}

Hot Reload

  1. src/index.js adresine gidiş rotasını izle. Karşılama mesajı kodunu 'Hello from Node' olarak düzenleyin.

Output penceresinde, Kubernetes: Run/Debug görünümünde, izleyicinin güncellenen dosyaları Kubernetes'teki kapsayıcıyla senkronize ettiğini hemen fark edeceksiniz.

Update initiated
File sync started for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
File sync succeeded for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
Update succeeded
  1. Kubernetes: Run/Debug - Detailed görünümüne geçerseniz dosya değişikliklerini tanıdığını ve düğümü yeniden başlattığını fark edersiniz.
files modified: [src/index.js]
Copying files:map[src/index.js:[/workspace/src/index.js]]togcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
Syncing 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a
Watching for changes...
[mynodejsapp]
[mynodejsapp]> mynodejsapp@1.0.0 start /workspace
[mynodejsapp]> node src/index.js
[mynodejsapp]
[mynodejsapp]Server running at: http://localhost:8080/
  1. Güncellenen sonuçları görmek için tarayıcınızı yenileyin.

Hata ayıklama

  1. Hata ayıklama görünümüne gidin ve mevcut iş parçacığını durdurun 647213126d7a4c7b.png.
  2. Alt menüde Cloud Code simgesini tıklayın ve uygulamayı debug modunda çalıştırmak için Debug on Kubernetes simgesini seçin.
  • Output penceresinin Kubernetes Run/Debug - Detailed görünümünde, Skaffold'un bu uygulamayı hata ayıklama modunda dağıtacağını unutmayın.
  • Uygulamanın oluşturulup dağıtılması birkaç dakika sürer. Bu kez bir hata ayıklayıcının eklendiğini fark edeceksiniz.
Port forwarding pod/mynodejsapp-6bbcf847cd-vqr6v in namespace default, remote port 9229 -> http://127.0.0.1:9229
[mynodejsapp]Debugger attached.
  1. Alt durum çubuğu, hata ayıklama modunda olduğunu belirtmek için rengini maviden turuncuya değiştirir.
  2. Kubernetes Run/Debug görünümünde, hata ayıklanabilir bir kapsayıcının başlatıldığını fark edin.
**************URLs*****************
Forwarded URL from service mynodejsapp-service: http://localhost:8080
Debuggable container started pod/mynodejsapp-deployment-6bc7598798-xl9kj:mynodejsapp (default)
Update succeeded
***********************************

Kesme noktalarından yararlanma

  1. src/index.js uygulamasını açın.
  2. var message="Greetings from Node"; ifadesini bulun.
  3. Satır numarasının solundaki boş alanı tıklayarak bu satıra kesme noktası ekleyin. Kesme noktasının ayarlandığını belirtmek için kırmızı bir gösterge gösterilir.
  4. Tarayıcınızı yeniden yükleyin. Hata ayıklayıcının, işlemi kesme noktasında durdurduğunu ve GKE'de uzaktan çalışan uygulamanın değişkenlerini ve durumunu incelemenize olanak tanıdığını unutmayın.
  5. "message" değişkenini bulana kadar değişkenler bölümünü tıklayın.
  6. Step over 7cfdee4fd6ef5c3a.png seçeneğine basarak satırı yürütün.
  7. "message" değişkeninin mevcut değerinin "Greetings from Node" olarak değiştiğini gözlemleyin.
  8. "Hedef" değişken adını çift tıklayın ve pop-up'ta değeri "Hello from Node" gibi farklı bir değerle değiştirin.
  9. Hata ayıklama kontrol panelinde Devam düğmesini tıklayın.
  10. Tarayıcınızda, az önce girdiğiniz güncellenmiş değeri gösteren yanıtı inceleyin.
  11. Durdur düğmesine 647213126d7a4c7b.png basarak "Hata ayıklama" modunu durdurun ve kesme noktasına tekrar tıklayarak kesme noktasını kaldırın.

5. Basit bir CRUD Rest hizmeti geliştirme

Bu noktada uygulamanız, container'lı geliştirme için tamamen yapılandırılmış ve Cloud Code ile temel geliştirme iş akışını tamamlamış olursunuz. Aşağıdaki bölümlerde, Google Cloud'da yönetilen bir veritabanına bağlanan REST hizmeti uç noktaları ekleyerek öğrendiklerinizi uygulayacaksınız.

Bağımlılıkları Yapılandırma

Uygulama kodu, geri kalan hizmet verilerini kalıcı hale getirmek için bir veritabanı kullanır. package.json dosyasına aşağıdakileri ekleyerek bağımlılıkların kullanılabilir olduğundan emin olun.

  1. Postgres'te CRUD uygulaması oluşturmak için package.json dosyasına iki bağımlılık daha (pg ve sequelize) ekleyin. Değişiklikleri yükleme sonrası bağımlılıklar bölümü şöyle görünür.
    "dependencies": {
    "express": "^4.16.4",
    "pg": "^8.7.3",
    "sequelize": "^6.17.0"
  }

REST hizmetini kodlama

  1. CRUD uygulama kodunu bu uygulamaya ekleyin.
wget -O app.zip https://github.com/GoogleCloudPlatform/container-developer-workshop/raw/main/labs/nodejs/app.zip

unzip app.zip

Bu kodun

  • item için varlık modelini içeren models klasörü
  • CRUD işlemlerini yapan kodun bulunduğu controllers klasörü
  • Belirli URL kalıplarını farklı çağrılara yönlendiren routes klasörü
  • Veritabanı bağlantı ayrıntılarını içeren config klasörü
  1. db.config.js dosyasındaki veritabanı yapılandırmasının, veritabanına bağlanmak için sağlanması gereken ortam değişkenlerini ifade ettiğini unutmayın. Ayrıca, gelen isteği URL kodlaması için ayrıştırmanız gerekir.
  2. src/index.js içine aşağıdaki kod snippet'ini ekleyerek app.listen(PORT, () => { ile başlayan son bölümden hemen önce ana JavaScript dosyanızdan CRUD koduna bağlanabilirsiniz.
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(
 bodyParser.urlencoded({
   extended: true,
 })
)
const db = require("../app/models");
db.sequelize.sync();
require("../app/routes/item.routes")(app);
  1. Veritabanı bağlantı bilgilerini sağlamak için ortam değişkenlerini eklemek üzere deployment.yaml dosyasındaki dağıtımı düzenleyin.

Dosyanın sonundaki özellik girişini aşağıdaki tanıma uyacak şekilde güncelleyin.

    spec:
      containers:
      - name: mynodejsapp
        image: mynodejsapp
        env:
        - name: DB_HOST
          value: ${DB_INSTANCE_IP}        
        - name: DB_PORT
          value: "5432"  
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: gke-cloud-sql-secrets
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: gke-cloud-sql-secrets
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: gke-cloud-sql-secrets
              key: database
  1. DB_HOST değerini veritabanınızın adresiyle değiştirin.
export DB_INSTANCE_IP=$(gcloud sql instances describe mytest-instance \
    --format=json | jq \
    --raw-output ".ipAddresses[].ipAddress")

envsubst < deployment.yaml > deployment.new && mv deployment.new deployment.yaml

Uygulamayı Dağıtma ve Doğrulama

  1. Cloud Shell Düzenleyici'nin alt kısmındaki bölmede Cloud Code simgesini, ardından ekranın üst kısmında Debug on Kubernetes simgesini seçin.
  2. Derleme ve testler tamamlandığında Çıkış sekmesinde Resource deployment/mynodejsapp status completed successfully ifadesi gösterilir ve "Forwarded URL from service mynodejsapp: http://localhost:8080" URL'si listelenir.
  3. Birkaç öğe ekleyin.

Cloud Shell terminalinden aşağıdaki komutları çalıştırın.

URL=localhost:8080
curl -X POST $URL/items -d '{"itemName":"Body Spray", "itemPrice":3.2}' -H "Content-Type: application/json"
curl -X POST $URL/items -d '{"itemName":"Nail Cutter", "itemPrice":2.5}' -H "Content-Type: application/json"
  1. Tarayıcıda $URL/items komutunu çalıştırarak GET'i test edin. Ayrıca curl'ü komut satırından da çalıştırabilirsiniz.
curl -X GET $URL/items
  1. Silme Testi: Şimdi aşağıdaki komutu çalıştırarak bir öğeyi silmeyi deneyin. Gerekirse item-id değerini değiştirin.
curl -X DELETE $URL/items/1
    This throws an error message
{"message":"Could not delete Item with id=[object Object]"}

Sorunu belirleme ve düzeltme

  1. Uygulamayı hata ayıklama modunda yeniden başlatın ve sorunu bulun. Aşağıda bazı ipuçları verilmiştir:
  • DELETE yönteminin istenen sonucu döndürmediği için bir sorun olduğunu biliyoruz. Bu nedenle, kesme noktasını itemcontroller.js->exports.delete yönteminde ayarlarsınız.
  • Adım adım yürütme işlemini çalıştırın ve sol penceredeki yerel değişkenlerin değerlerini gözlemlemek için her adımda değişkenleri izleyin.
  • request.params gibi belirli değerleri gözlemlemek için bu değişkeni İzleme penceresine ekleyin.
  1. id öğesine atanan değerin undefined olduğunu unutmayın. Sorunu düzeltmek için kodu değiştirin.

Düzeltilmiş kod snippet'i şöyle görünür.

// Delete a Item with the specified id in the request
exports.delete = (req, res) => {
    const id = req.params.id;
  1. Uygulama yeniden başlatıldıktan sonra silmeyi deneyerek tekrar test edin.
  2. Hata ayıklama araç çubuğundaki kırmızı kareyi tıklayarak hata ayıklama oturumunu durdurun. 647213126d7a4c7b.png

6. Temizleme

Tebrikler! Bu laboratuvarda sıfırdan yeni bir Node.js uygulaması oluşturdunuz ve bu uygulamayı, container'larla birlikte anında dağıtım modunda çalışacak şekilde yapılandırdınız. Ardından, geleneksel uygulama yığınlarında bulunan geliştirici akışını izleyerek uygulamanızı uzak bir GKE kümesine dağıtıp hatalarını ayıklarsınız.

Laboratuvarı tamamladıktan sonra temizlik yapmak için:

  1. Laboratuvarda kullanılan dosyaları silin.
cd ~ && rm -rf mynodejsapp && rm -f setup.sh
  1. İlgili tüm altyapıyı ve kaynakları kaldırmak için projeyi silin.