{"id":1181,"date":"2025-09-08T11:16:30","date_gmt":"2025-09-08T11:16:30","guid":{"rendered":"https:\/\/davidka.net\/?p=1181"},"modified":"2025-09-15T23:57:32","modified_gmt":"2025-09-15T21:57:32","slug":"ci-cd-from-basics-to-production","status":"publish","type":"post","link":"https:\/\/de.davidka.net\/de\/2025\/09\/08\/ci-cd-from-basics-to-production\/","title":{"rendered":""},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">\ud83d\ude80 <strong>CI\/CD: Von den Grundlagen bis zur Produktion auf GCP mit GitHub Actions \u2013 Ein vollst\u00e4ndiger Leitfaden mit Beispielen<\/strong> \ud83d\ude80<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hallo, Entwickler! In diesem Artikel werde ich \u00fcber CI\/CD sprechen \u2013 ein Konzept.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Was ist eine CI\/CD-Pipeline im Kontext der Programmierung?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Eine CI\/CD-Pipeline (Continuous Integration \/ Continuous Delivery oder Continuous Deployment)<\/strong> ist ein automatisierter Prozess, der es Entwicklern erm\u00f6glicht, Code\u00e4nderungen schnell und zuverl\u00e4ssig in eine Produktionsumgebung zu liefern.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Lassen Sie uns die Schl\u00fcsselkonzepte aufschl\u00fcsseln:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udd27 <strong>CI \u2014 Continuous Integration (Kontinuierliche Integration)<\/strong><br>Dies ist eine Praxis, bei der Entwickler h\u00e4ufig \u00c4nderungen in eine gemeinsame Codebasis integrieren. Jede solche \u00c4nderung wird automatisch: * <strong>Gebaut<\/strong> (build) * <strong>Getestet<\/strong> (Unit-Tests, Integrationstests) * <strong>Auf Einhaltung von Standards \u00fcberpr\u00fcft<\/strong> (Linting, statische Analyse)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49 **Ziel von CI:** Fehler so fr\u00fch wie m\u00f6glich zu identifizieren, bevor sie etwas Wichtiges kaputt machen oder in ein Release gelangen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\ude80 **CD \u2014 Continuous Delivery (Kontinuierliche Bereitstellung) oder Continuous Deployment (Kontinuierliche Auslieferung)**<br>Hier gibt es zwei Optionen:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u2705 **Continuous Delivery (Kontinuierliche Bereitstellung)**<br>Nach erfolgreichem Abschluss der CI-Phase werden \u00c4nderungen automatisch: * Zus\u00e4tzlichen Tests unterzogen (z. B. E2E \u2013 End-to-End-Tests) * Auf einem Staging-Server (Testserver) bereitgestellt<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49 **Aber die Bereitstellung in die Produktion erfordert immer noch eine manuelle Best\u00e4tigung.** Dies gibt dem Team die Kontrolle dar\u00fcber, *wann* genau die Benutzer die \u00c4nderungen sehen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83e\udd16 **Continuous Deployment (Kontinuierliche Auslieferung)**<br>Dies ist der n\u00e4chste Schritt nach Continuous Delivery. Hier erfolgt die Bereitstellung in die Produktion **vollautomatisch**, wenn alle vorherigen Phasen der Pipeline (Build, alle Tests) erfolgreich waren. Dies ist die fortschrittlichste Stufe der Automatisierung.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd04 Woraus besteht eine CI\/CD-Pipeline normalerweise?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Eine typische Pipeline umfasst die folgenden Phasen:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Checkout<\/strong> \u2014 Klonen der neuesten Codeversion aus dem Repository.<\/li>\n\n\n\n<li><strong>Build<\/strong> \u2014 Erstellen des Projekts (Kompilierung, Erstellung von Artefakten, Docker-Images).<\/li>\n\n\n\n<li><strong>Test<\/strong> \u2014 Ausf\u00fchren verschiedener Arten von Tests (Unit-, Integrations-, E2E).<\/li>\n\n\n\n<li><strong>Lint\/Code Quality<\/strong> \u2014 \u00dcberpr\u00fcfung des Codes auf Stilkonformit\u00e4t und potenzielle Fehler mithilfe statischer Analysetools.<\/li>\n\n\n\n<li><strong>Deploy<\/strong> \u2014 Bereitstellen der Anwendung (auf einem Staging- oder Produktionsserver).<\/li>\n\n\n\n<li><strong>Notify<\/strong> \u2014 Senden von Benachrichtigungen \u00fcber den Pipeline-Status an das Team (z. B. in Slack, E-Mail).<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udee0 Beliebte Tools f\u00fcr CI\/CD:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>GitHub Actions<\/strong> (unser heutiger Fokus!)<\/li>\n\n\n\n<li>GitLab CI\/CD<\/li>\n\n\n\n<li>Jenkins<\/li>\n\n\n\n<li>CircleCI<\/li>\n\n\n\n<li>Bitbucket Pipelines<\/li>\n\n\n\n<li>Azure DevOps<\/li>\n\n\n\n<li>TeamCity<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83e\udde0 Warum brauchen wir CI\/CD \u00fcberhaupt?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Reduziert menschliche Fehler:<\/strong> Automatisierung eliminiert Fehler, die mit manuellen Operationen verbunden sind.<\/li>\n\n\n\n<li><strong>Schnelle Fehlererkennung:<\/strong> Fehler werden fr\u00fcher gefunden, was ihre Behebung einfacher und kosteng\u00fcnstiger macht.<\/li>\n\n\n\n<li><strong>Automatisierung von Routineaufgaben:<\/strong> Entwickler verbringen weniger Zeit mit dem Bauen und Bereitstellen und mehr Zeit mit dem Codieren.<\/li>\n\n\n\n<li><strong>Verbesserung der Codequalit\u00e4t:<\/strong> Kontinuierliche \u00dcberpr\u00fcfungen und Tests erh\u00f6hen den allgemeinen Qualit\u00e4tsstandard.<\/li>\n\n\n\n<li><strong>Schnelle Bereitstellung von Funktionen f\u00fcr Benutzer:<\/strong> Neue Funktionen erreichen den Endbenutzer schneller und h\u00e4ufiger.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udce6 Einfache CI\/CD-Beispiele mit GitHub Actions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Schauen wir uns grundlegende Pipelines f\u00fcr beliebte Technologien an. Alle Beispiele verwenden GitHub Actions und werden im Verzeichnis <code class=\"\" data-line=\"\">.github\/workflows\/<\/code> Ihres Projekts gespeichert.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc0d CI\/CD f\u00fcr Python (mit <code class=\"\" data-line=\"\">pytest<\/code> und <code class=\"\" data-line=\"\">flake8<\/code>)<\/h4>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/python-ci.yml\nname: Python CI\n\non: &#091;push, pull_request]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions\/checkout@v3\n\n      - name: Set up Python\n        uses: actions\/setup-python@v4\n        with:\n          python-version: &#039;3.11&#039; # Geben Sie Ihre Version an\n\n      - name: Install dependencies\n        run: |\n          python -m pip install --upgrade pip\n          pip install -r requirements.txt # Stellen Sie sicher, dass Sie requirements.txt haben\n          pip install flake8 pytest\n\n      - name: Lint with flake8\n        run: |\n          # \u00dcberpr\u00fcfen Sie den Code in den Ordnern src und tests (passen Sie ihn an Ihr Projekt an)\n          flake8 src tests\n\n      - name: Run tests\n        run: |\n          pytest\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83c\udf10 CI\/CD f\u00fcr Node.js (mit <code class=\"\" data-line=\"\">npm test<\/code> und <code class=\"\" data-line=\"\">eslint<\/code>)<\/h4>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/node-ci.yml\nname: Node.js CI\n\non: &#091;push, pull_request]\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version: &#091;18.x] # Geben Sie Ihre Node.js-Version an\n\n    steps:\n      - uses: actions\/checkout@v3\n\n      - name: Use Node.js ${{ matrix.node-version }}\n        uses: actions\/setup-node@v4\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - name: Install dependencies\n        run: npm install # oder npm ci f\u00fcr eine vorhersehbarere Installation\n\n      - name: Lint with ESLint\n        run: npx eslint . # Stellen Sie sicher, dass ESLint im Projekt konfiguriert ist\n\n      - name: Run tests\n        run: npm test\n<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udc33 CI\/CD f\u00fcr Docker (Build und Push zu Docker Hub)<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr dieses Beispiel ben\u00f6tigen Sie die Geheimnisse <code class=\"\" data-line=\"\">DOCKER_USERNAME<\/code> und <code class=\"\" data-line=\"\">DOCKER_PASSWORD<\/code> (oder ein Token) in den Einstellungen Ihres GitHub-Repositorys (<code class=\"\" data-line=\"\">Settings -&gt; Secrets and variables -&gt; Actions<\/code>).<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/docker-ci.yml\nname: Docker CI\/CD\n\non:\n  push:\n    branches: &#091; main ] # Nur f\u00fcr den main-Branch ausf\u00fchren\n\njobs:\n  docker:\n    runs-on: ubuntu-latest\n\n    steps:\n      - uses: actions\/checkout@v3\n\n      - name: Log in to Docker Hub\n        run: echo &quot;${{ secrets.DOCKER_PASSWORD }}&quot; | docker login -u &quot;${{ secrets.DOCKER_USERNAME }}&quot; --password-stdin\n\n      - name: Build Docker image\n        # Ersetzen Sie myapp durch den Namen Ihrer Anwendung\n        run: docker build -t ${{ secrets.DOCKER_USERNAME }}\/myapp:latest .\n\n      - name: Push Docker image\n        run: docker push ${{ secrets.DOCKER_USERNAME }}\/myapp:latest\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\ude9a Bereitstellung auf beliebten Plattformen<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nachdem wir nun gebaute und getestete Artefakte (z. B. ein Docker-Image) haben, schauen wir uns an, wie sie bereitgestellt werden k\u00f6nnen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">\ud83d\udfe3 Bereitstellung auf Heroku<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\ud83d\udd10 GitHub-Geheimnisse:<\/strong> <code class=\"\" data-line=\"\">HEROKU_API_KEY<\/code>, <code class=\"\" data-line=\"\">HEROKU_APP_NAME<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/deploy-heroku.yml\nname: Deploy to Heroku\n\non:\n  push:\n    branches: &#091;main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v3\n      - name: Install Heroku CLI\n        run: curl https:\/\/cli-assets.heroku.com\/install.sh | sh\n      - name: Login to Heroku\n        env:\n          HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}\n        run: heroku auth:token\n      - name: Deploy to Heroku\n        env:\n          HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}\n        run: |\n          heroku git:remote -a ${{ secrets.HEROKU_APP_NAME }}\n          git push heroku main -f # Seien Sie vorsichtig mit -f (force push)\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn Sie ein Docker-Image auf Heroku bereitstellen:<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># ... (Build- und Login-Schritte f\u00fcr Docker Hub\/GHCR aus fr\u00fcheren Beispielen) ...\n# deploy:\n#   name: Deploy to Heroku\n#   needs: build # Abh\u00e4ngig vom Build-Job des Images\n#   runs-on: ubuntu-latest\n#   steps:\n#     # ...\n#     - name: Login to Heroku container registry\n#       run: echo &quot;${{ secrets.HEROKU_API_KEY }}&quot; | docker login --username=_ --password-stdin registry.heroku.com\n#     - name: Tag image for Heroku\n#       # Angenommen, das Image wird als ghcr.io\/username\/repo\/myapp:latest gebaut\n#       run: docker tag ghcr.io\/${{ github.repository_owner }}\/${{ github.event.repository.name }}\/myapp:latest registry.heroku.com\/${{ secrets.HEROKU_APP_NAME }}\/web\n#     - name: Push image to Heroku\n#       run: docker push registry.heroku.com\/${{ secrets.HEROKU_APP_NAME }}\/web\n#     - name: Release Heroku App\n#       env:\n#         HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}\n#       run: heroku container:release web --app ${{ secrets.HEROKU_APP_NAME }}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udfe8 Bereitstellung auf AWS (z. B. statische Dateien in S3)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\ud83d\udd10 GitHub-Geheimnisse:<\/strong> <code class=\"\" data-line=\"\">AWS_ACCESS_KEY_ID<\/code>, <code class=\"\" data-line=\"\">AWS_SECRET_ACCESS_KEY<\/code>, <code class=\"\" data-line=\"\">AWS_REGION<\/code>, <code class=\"\" data-line=\"\">S3_BUCKET_NAME<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/deploy-aws-s3.yml\nname: Deploy Static Site to AWS S3\n\non:\n  push:\n    branches: &#091;main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v3\n      - name: Configure AWS credentials\n        uses: aws-actions\/configure-aws-credentials@v4\n        with:\n          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}\n          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n          aws-region: ${{ secrets.AWS_REGION }}\n      - name: Sync files to S3\n        # Ersetzen Sie .\/public durch den Pfad zu Ihren statischen Dateien\n        run: aws s3 sync .\/public s3:\/\/${{ secrets.S3_BUCKET_NAME }} --delete\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr die Bereitstellung auf **AWS Elastic Beanstalk** wird normalerweise die EB CLI verwendet, die Pipeline ist \u00e4hnlich, aber mit <code class=\"\" data-line=\"\">eb deploy<\/code>-Befehlen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd35 Bereitstellung auf Google Cloud Platform (GCP App Engine)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>\ud83d\udd10 GitHub-Geheimnisse:<\/strong> <code class=\"\" data-line=\"\">GCP_CREDENTIALS<\/code> (JSON-Schl\u00fcssel des Dienstkontos), <code class=\"\" data-line=\"\">GCP_PROJECT_ID<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/deploy-gcp-app-engine.yml\nname: Deploy to GCP App Engine\n\non:\n  push:\n    branches: &#091;main]\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v3\n      - name: Set up Cloud SDK\n        uses: google-github-actions\/setup-gcloud@v2\n        with:\n          project_id: ${{ secrets.GCP_PROJECT_ID }}\n          service_account_key: ${{ secrets.GCP_CREDENTIALS }}\n          export_default_credentials: true\n      - name: Deploy to App Engine\n        # Stellen Sie sicher, dass Sie app.yaml im Stammverzeichnis des Projekts haben\n        run: gcloud app deploy --quiet\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udfea Bereitstellung auf Render.com<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Render stellt oft automatisch bei einem Push zu GitHub bereit, wenn das Repository verbunden ist. Aber f\u00fcr einen manuellen Trigger (oder als Teil einer komplexeren Pipeline) kann ein Deploy Hook verwendet werden.<br><strong>\ud83d\udd10 GitHub-Geheimnisse:<\/strong> <code class=\"\" data-line=\"\">RENDER_DEPLOY_HOOK<\/code> (URL, die aus den Render-Diensteinstellungen abgerufen wird).<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/deploy-render.yml\nname: Trigger Render Deploy\n\non:\n  workflow_dispatch: # Manueller Start \u00fcber die GitHub-UI\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Trigger Render Deploy Hook\n        run: curl -X POST ${{ secrets.RENDER_DEPLOY_HOOK }}\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83c\udf1f Fortgeschrittenes CI\/CD: Docker bauen \u2192 Push zu GHCR \u2192 Staging\/Production auf GCP Cloud Run<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Und jetzt das Sahneh\u00e4ubchen! Lassen Sie uns eine fortgeschrittene Pipeline zusammenstellen:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Build des Docker-Images.<\/li>\n\n\n\n<li>Ver\u00f6ffentlichung des Images im GitHub Container Registry (ghcr.io).<\/li>\n\n\n\n<li>Automatische Bereitstellung in die **Staging**-Umgebung auf GCP Cloud Run.<\/li>\n\n\n\n<li>Bereitstellung in die **Produktions**-Umgebung auf GCP Cloud Run **nach manueller Best\u00e4tigung**.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Daf\u00fcr ben\u00f6tigen wir mehrere Workflow-Dateien.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Erforderliche GitHub-Geheimnisse:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code class=\"\" data-line=\"\">GCP_PROJECT_ID<\/code>: ID Ihres GCP-Projekts.<\/li>\n\n\n\n<li><code class=\"\" data-line=\"\">GCP_CREDENTIALS<\/code>: JSON-Schl\u00fcssel des GCP-Dienstkontos mit Berechtigungen zur Bereitstellung in Cloud Run und Zugriff auf GHCR (falls erforderlich). Normalerweise reicht <code class=\"\" data-line=\"\">GITHUB_TOKEN<\/code> f\u00fcr den Zugriff auf GHCR von Actions aus.<\/li>\n\n\n\n<li><code class=\"\" data-line=\"\">GCP_REGION<\/code>: Region f\u00fcr Cloud Run (z. B. <code class=\"\" data-line=\"\">europe-west1<\/code>).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">1. Build und Ver\u00f6ffentlichung des Docker-Images in GHCR<\/h3>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/build.yml\nname: Build &amp; Push to GHCR\n\non:\n  push:\n    branches: &#091;main] # Bei Push zu main ausf\u00fchren\n\njobs:\n  build-and-push:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read      # F\u00fcr Checkout\n      packages: write     # F\u00fcr Push zu GHCR\n\n    steps:\n      - uses: actions\/checkout@v3\n\n      - name: Log in to GitHub Container Registry\n        uses: docker\/login-action@v3\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Build and push Docker image\n        uses: docker\/build-push-action@v5\n        with:\n          context: .\n          push: true\n          tags: ghcr.io\/${{ github.repository_owner }}\/${{ github.event.repository.name }}\/myapp:latest\n          # Sie k\u00f6nnen eine Tagging nach Commit-SHA f\u00fcr Einzigartigkeit hinzuf\u00fcgen:\n          # tags: |\n          #   ghcr.io\/${{ github.repository_owner }}\/${{ github.event.repository.name }}\/myapp:latest\n          #   ghcr.io\/${{ github.repository_owner }}\/${{ github.event.repository.name }}\/myapp:${{ github.sha }}\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code class=\"\" data-line=\"\">github.repository_owner<\/code>: Besitzer des Repositorys (Ihr Benutzername oder Ihre Organisation).<\/li>\n\n\n\n<li><code class=\"\" data-line=\"\">github.event.repository.name<\/code>: Name des Repositorys.<\/li>\n\n\n\n<li><code class=\"\" data-line=\"\">myapp<\/code>: Name Ihrer Anwendung\/Ihres Images.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">2. Automatische Bereitstellung in Staging (GCP Cloud Run)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dieser Workflow wird automatisch nach erfolgreichem Abschluss von <code class=\"\" data-line=\"\">build.yml<\/code> ausgef\u00fchrt.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/deploy-staging.yml\nname: Deploy to GCP Cloud Run (Staging)\n\non:\n  workflow_run:\n    workflows: &#091;&quot;Build &amp; Push to GHCR&quot;]\n    types:\n      - completed\n\njobs:\n  deploy-staging:\n    runs-on: ubuntu-latest\n    if: ${{ github.event.workflow_run.conclusion == &#039;success&#039; }}\n\n    environment:\n      name: staging\n      url: ${{ steps.deploy.outputs.url }}\n\n    steps:\n      - uses: actions\/checkout@v3\n\n      - id: &#039;auth&#039;\n        uses: &#039;google-github-actions\/auth@v2&#039;\n        with:\n          credentials_json: &#039;${{ secrets.GCP_CREDENTIALS }}&#039;\n\n      - name: &#039;Deploy to Cloud Run (Staging)&#039;\n        id: deploy\n        uses: &#039;google-github-actions\/deploy-cloudrun@v2&#039;\n        with:\n          service: &#039;myapp-staging&#039;\n          region: &#039;${{ secrets.GCP_REGION }}&#039;\n          image: &#039;ghcr.io\/${{ github.repository_owner }}\/${{ github.event.repository.name }}\/myapp:latest&#039;\n          project_id: &#039;${{ secrets.GCP_PROJECT_ID }}&#039;\n          flags: &#039;--allow-unauthenticated --platform=managed&#039;\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. Bereitstellung in Produktion mit manueller Best\u00e4tigung (GCP Cloud Run)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dieser Workflow wird manuell \u00fcber die GitHub Actions-Benutzeroberfl\u00e4che ausgel\u00f6st.<\/p>\n\n\n\n<pre class=\"wp-block-code line-numbers\"><code class=\" language-python\" data-line=\"\"># .github\/workflows\/deploy-prod.yml\nname: Deploy to GCP Cloud Run (Production)\n\non:\n  workflow_dispatch: # Erm\u00f6glicht manuellen Start\n\njobs:\n  deploy-production:\n    runs-on: ubuntu-latest\n\n    environment:\n      name: production\n      url: ${{ steps.deploy.outputs.url }}\n\n    steps:\n      - uses: actions\/checkout@v3\n\n      - id: &#039;auth&#039;\n        uses: &#039;google-github-actions\/auth@v2&#039;\n        with:\n          credentials_json: &#039;${{ secrets.GCP_CREDENTIALS }}&#039;\n\n      - name: &#039;Deploy to Cloud Run (Production)&#039;\n        id: deploy\n        uses: &#039;google-github-actions\/deploy-cloudrun@v2&#039;\n        with:\n          service: &#039;myapp-production&#039;\n          region: &#039;${{ secrets.GCP_REGION }}&#039;\n          image: &#039;ghcr.io\/${{ github.repository_owner }}\/${{ github.event.repository.name }}\/myapp:latest&#039;\n          project_id: &#039;${{ secrets.GCP_PROJECT_ID }}&#039;\n          flags: &#039;--allow-unauthenticated --platform=managed&#039;\n          # F\u00fcr die Produktion k\u00f6nnen Sie --no-traffic hinzuf\u00fcgen und dann den Traffic schrittweise umschalten\n          # traffic:\n          #   latest: true\n          #   percent: 100\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Wichtige Punkte dieser fortgeschrittenen Pipeline:<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>GitHub Container Registry (ghcr.io):<\/strong> Wir verwenden es zum Speichern von Docker-Images. Dies ist praktisch, da es eng in GitHub Actions integriert ist.<\/li>\n\n\n\n<li><strong><code class=\"\" data-line=\"\">workflow_run<\/code>:<\/strong> Erm\u00f6glicht das Ausf\u00fchren eines Workflows (Staging-Bereitstellung) nach Abschluss eines anderen (Build).<\/li>\n\n\n\n<li><strong><code class=\"\" data-line=\"\">workflow_dispatch<\/code>:<\/strong> Bietet die M\u00f6glichkeit, einen Workflow (Produktionsbereitstellung) manuell auszul\u00f6sen, was die Kontrolle gew\u00e4hrleistet.<\/li>\n\n\n\n<li><strong>GitHub Environments:<\/strong> Erm\u00f6glichen es Ihnen, Schutzregeln f\u00fcr die Produktion zu konfigurieren (z. B. die Genehmigung durch bestimmte Pr\u00fcfer zu verlangen) und umgebungsspezifische Geheimnisse zu speichern.<\/li>\n\n\n\n<li><strong>GCP Cloud Run:<\/strong> Eine ausgezeichnete Serverless-Option zum Ausf\u00fchren von containerisierten Anwendungen.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\ud83d\udd10 Sicherheit \u2013 das ist wichtig!<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Verwenden Sie GitHub Secrets:<\/strong> Speichern Sie niemals Token, Passw\u00f6rter, API-Schl\u00fcssel direkt in YAML-Dateien. Verwenden Sie <code class=\"\" data-line=\"\">Settings -&gt; Secrets and variables -&gt; Actions<\/code> in Ihrem Repository.<\/li>\n\n\n\n<li><strong>Minimale Berechtigungen:<\/strong> Gew\u00e4hren Sie Dienstkonten (z. B. GCP) nur die Berechtigungen, die f\u00fcr die Ausf\u00fchrung von CI\/CD-Aufgaben unbedingt erforderlich sind.<\/li>\n\n\n\n<li><strong>Umgebungen isolieren:<\/strong> Staging und Produktion sollten so weit wie m\u00f6glich isoliert sein. Unterschiedliche Projekte\/Konten bei Cloud-Anbietern sind eine gute Praxis.<\/li>\n\n\n\n<li><strong>Branch-Schutz:<\/strong> Konfigurieren Sie den Schutz f\u00fcr den <code class=\"\" data-line=\"\">main<\/code>&#8211; (oder <code class=\"\" data-line=\"\">master<\/code>)-Branch, sodass Pushs nur \u00fcber Pull Requests mit obligatorischen CI-Pr\u00fcfungen m\u00f6glich sind.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\ude80 CI\/CD: Von den Grundlagen bis zur Produktion auf GCP mit GitHub Actions \u2013 Ein vollst\u00e4ndiger Leitfaden mit Beispielen \ud83d\ude80 Hallo, Entwickler! In diesem Artikel werde ich \u00fcber CI\/CD sprechen \u2013 ein Konzept. Was ist eine CI\/CD-Pipeline im Kontext der Programmierung? Eine CI\/CD-Pipeline (Continuous Integration \/ Continuous Delivery oder Continuous Deployment) ist ein automatisierter Prozess,&hellip;&nbsp;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"off","neve_meta_content_width":70,"neve_meta_title_alignment":"left","neve_meta_author_avatar":"on","neve_post_elements_order":"[\"content\",\"tags\",\"comments\"]","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","_themeisle_gutenberg_block_has_review":false,"footnotes":""},"categories":[],"tags":[],"class_list":["post-1181","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/de.davidka.net\/de\/wp-json\/wp\/v2\/posts\/1181","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/de.davidka.net\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/de.davidka.net\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/de.davidka.net\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/de.davidka.net\/de\/wp-json\/wp\/v2\/comments?post=1181"}],"version-history":[{"count":0,"href":"https:\/\/de.davidka.net\/de\/wp-json\/wp\/v2\/posts\/1181\/revisions"}],"wp:attachment":[{"href":"https:\/\/de.davidka.net\/de\/wp-json\/wp\/v2\/media?parent=1181"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/de.davidka.net\/de\/wp-json\/wp\/v2\/categories?post=1181"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/de.davidka.net\/de\/wp-json\/wp\/v2\/tags?post=1181"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}