From 3766501933e76ae4ee7db776e68a898ae7ed74a3 Mon Sep 17 00:00:00 2001 From: romamatran Date: Fri, 10 Jul 2026 15:34:45 +0300 Subject: [PATCH 1/8] Delete .github/workflows/docker-image-pr.yml --- .github/workflows/docker-image-pr.yml | 101 -------------------------- 1 file changed, 101 deletions(-) delete mode 100644 .github/workflows/docker-image-pr.yml diff --git a/.github/workflows/docker-image-pr.yml b/.github/workflows/docker-image-pr.yml deleted file mode 100644 index 4556fe160..000000000 --- a/.github/workflows/docker-image-pr.yml +++ /dev/null @@ -1,101 +0,0 @@ -name: Docker Image CI - -on: - push: - branches: [ "develop" ] - pull_request: - branches: [ "develop" ] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Build the Docker image - run: docker build . --file Dockerfile --tag grandnode2:pr-latest - - - name: Start MongoDB container - run: | - docker run --name mongodb-container -d -p 27017:27017 mongo:latest - - - name: Wait for MongoDB to be ready - run: | - echo "Waiting for MongoDB to start..." - for i in {1..10}; do - nc -z localhost 27017 && echo "MongoDB is up" && break - echo "Retrying in 3 seconds..." - echo "Container logs:" - docker logs grandnode2-container --tail 20 - sleep 3 - done - - - name: List Docker images - run: docker images - - - - name: Run the application container - run: | - docker run --name grandnode2-container -d -p 8080:8080 --link mongodb-container:mongo grandnode2:pr-latest - - - name: Wait for the application to be ready - run: | - echo "Waiting for the application to start..." - for i in {1..10}; do - curl -s http://localhost:8080 && echo "Application is up!" && break - echo "Retrying in 3 seconds..." - sleep 3 - done - - - name: Trigger the installer via POST request - run: | - echo "Running installation with form-data..." - curl -X POST http://localhost:8080/install \ - -H "Content-Type: multipart/form-data" \ - -F "AdminEmail=admin@example.com" \ - -F "AdminPassword=SecurePassword123" \ - -F "ConfirmPassword=SecurePassword123" \ - -F "DataProvider=0" \ - -F "MongoDBServerName=mongo" \ - -F "MongoDBDatabaseName=grandnode" \ - -F "InstallSampleData=true" \ - -F "CompanyName=My Company" \ - -F "CompanyAddress=123 Main St" \ - -F "CompanyPhoneNumber=1234567890" \ - -F "CompanyEmail=info@company.com" - - - name: Restart the application container - run: | - docker restart grandnode2-container - - - name: Test HTTP response after installation - run: | - echo "Waiting for the application to start..." - for i in {1..10}; do - RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080 || echo "error") - if [ "$RESPONSE" = "200" ]; then - echo "Application is up with HTTP 200 response!" - exit 0 - elif [ "$RESPONSE" = "error" ]; then - echo "Curl encountered an error. Retrying in 3 seconds..." - else - echo "Received HTTP response code: $RESPONSE. Retrying in 3 seconds..." - fi - echo "Container logs:" - docker logs grandnode2-container --tail 30 - sleep 3 - done - echo "Application did not start successfully. Final response code: $RESPONSE" - exit 1 - - - name: Show container logs - run: | - echo "=== Full container logs ===" - docker logs grandnode2-container - echo "=== Container status ===" - docker inspect grandnode2-container --format='{{.State.Status}} - Exit: {{.State.ExitCode}}' - - - name: Stop and remove the container - run: | - docker stop grandnode2-container - docker rm grandnode2-container \ No newline at end of file From a74ff806e8c49b2cbf37ea0a0a24b41010a2307f Mon Sep 17 00:00:00 2001 From: romamatran Date: Fri, 10 Jul 2026 15:34:53 +0300 Subject: [PATCH 2/8] Delete .github/workflows/docker-image.yml --- .github/workflows/docker-image.yml | 167 ----------------------------- 1 file changed, 167 deletions(-) delete mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index 43bdb3740..000000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,167 +0,0 @@ -name: Docker Image CI - -on: - push: - branches: - - main - - develop - - workflow_dispatch: - - -permissions: - contents: read - packages: write - - -env: - IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/grancaffe - - -jobs: - - build: - - name: Build and Push Docker Image - - runs-on: ubuntu-latest - - - steps: - - - ################################# - # Checkout source code - ################################# - - - name: Checkout repository - uses: actions/checkout@v4 - - - - ################################# - # Docker setup - ################################# - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - - ################################# - # Login GHCR - ################################# - - - name: Login to GitHub Container Registry - - uses: docker/login-action@v3 - - with: - - registry: ghcr.io - - username: ${{ github.actor }} - - password: ${{ secrets.GITHUB_TOKEN }} - - - - ################################# - # Define image tag - ################################# - - - name: Set image tag - - shell: bash - - run: | - - if [ "${{ github.ref_name }}" = "main" ]; then - - echo "IMAGE_TAG=latest" >> $GITHUB_ENV - - else - - echo "IMAGE_TAG=develop" >> $GITHUB_ENV - - fi - - - - ################################# - # Docker metadata - ################################# - - - name: Docker metadata - - id: meta - - uses: docker/metadata-action@v5 - - with: - - images: ${{ env.IMAGE_NAME }} - - tags: | - - type=raw,value=${{ env.IMAGE_TAG }} - - type=sha - - - - ################################# - # Build and push image - ################################# - - - name: Build and push Docker image - - uses: docker/build-push-action@v6 - - - with: - - context: . - - - file: ./Dockerfile - - - push: true - - - platforms: linux/amd64 - - - tags: | - - ${{ steps.meta.outputs.tags }} - - - labels: | - - ${{ steps.meta.outputs.labels }} - - - - build-args: | - - GIT_COMMIT=${{ github.sha }} - - GIT_BRANCH=${{ github.ref_name }} - - - - cache-from: | - - type=gha - - - - cache-to: | - - type=gha,mode=max From 589c856853655f482d766a5558cbdb59719f8a6b Mon Sep 17 00:00:00 2001 From: romamatran Date: Fri, 10 Jul 2026 15:35:00 +0300 Subject: [PATCH 3/8] Delete .github/workflows/test-ssh.yml --- .github/workflows/test-ssh.yml | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 .github/workflows/test-ssh.yml diff --git a/.github/workflows/test-ssh.yml b/.github/workflows/test-ssh.yml deleted file mode 100644 index 9f7653091..000000000 --- a/.github/workflows/test-ssh.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Test SSH Connection - -on: - workflow_dispatch: - -jobs: - test: - - runs-on: ubuntu-latest - - steps: - - - name: Test SSH connection - - uses: appleboy/ssh-action@v1.2.0 - - with: - host: ${{ secrets.DO_HOST }} - username: ${{ secrets.DO_USER }} - key: ${{ secrets.DO_SSH_KEY }} - - script: | - echo "Connected successfully" - hostname - whoami - docker --version From c6b863d01ebfe3cca3ef4b09ebcab306eae4ff21 Mon Sep 17 00:00:00 2001 From: romamatran Date: Fri, 10 Jul 2026 15:35:13 +0300 Subject: [PATCH 4/8] Delete .github/workflows/deploy-production.yml --- .github/workflows/deploy-production.yml | 279 ------------------------ 1 file changed, 279 deletions(-) delete mode 100644 .github/workflows/deploy-production.yml diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml deleted file mode 100644 index db2ce1cf2..000000000 --- a/.github/workflows/deploy-production.yml +++ /dev/null @@ -1,279 +0,0 @@ -name: Deploy GranCaffe Production - - -on: - - push: - branches: - - develop - - workflow_dispatch: - - - -permissions: - - contents: read - packages: write - - - -env: - - IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/grancaffe - - - -jobs: - - - build-and-deploy: - - - name: Build Docker image and deploy - - runs-on: ubuntu-latest - - - - steps: - - - ######################################## - # Checkout - ######################################## - - - name: Checkout source code - - uses: actions/checkout@v4 - - - - ######################################## - # Docker Buildx - ######################################## - - - name: Setup Docker Buildx - - uses: docker/setup-buildx-action@v3 - - - - ######################################## - # Login GHCR - ######################################## - - - name: Login GitHub Container Registry - - uses: docker/login-action@v3 - - with: - - registry: ghcr.io - - username: ${{ github.actor }} - - password: ${{ secrets.GITHUB_TOKEN }} - - - - ######################################## - # Docker metadata - ######################################## - - - name: Docker metadata - - id: meta - - uses: docker/metadata-action@v5 - - with: - - images: ${{ env.IMAGE_NAME }} - - tags: | - - type=raw,value=latest - - type=sha - - - - ######################################## - # Build and push image - ######################################## - - - name: Build and push Docker image - - uses: docker/build-push-action@v6 - - - with: - - context: . - - file: ./Dockerfile - - push: true - - - platforms: linux/amd64 - - - tags: | - - ${{ steps.meta.outputs.tags }} - - - labels: | - - ${{ steps.meta.outputs.labels }} - - - build-args: | - - GIT_COMMIT=${{ github.sha }} - - GIT_BRANCH=${{ github.ref_name }} - - - cache-from: | - - type=gha - - - cache-to: | - - type=gha,mode=max - - - - - - ######################################## - # Deploy DigitalOcean - ######################################## - - - name: Deploy to DigitalOcean Droplet - - - uses: appleboy/ssh-action@v1.2.0 - - - with: - - - host: ${{ secrets.DO_HOST }} - - - username: ${{ secrets.DO_USER }} - - - key: ${{ secrets.DO_SSH_KEY }} - - - script: | - - - set -e - - - - echo "Go to application directory" - - - cd /opt/grancaffe - - - - - echo "Login GHCR" - - - echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u romamatran --password-stdin - - - - - echo "Pull latest image" - - - docker compose pull - - - - - echo "Restart containers" - - - docker compose up -d --remove-orphans - - - - - echo "Cleanup old images" - - - docker image prune -f - - - - - echo "Deployment completed" - - - - - - ######################################## - # Verify - ######################################## - - - name: Health check - - - uses: appleboy/ssh-action@v1.2.0 - - - with: - - - host: ${{ secrets.DO_HOST }} - - - username: ${{ secrets.DO_USER }} - - - key: ${{ secrets.DO_SSH_KEY }} - - - script: | - - - set -e - - - - echo "Containers status" - - - docker ps - - - - echo "Waiting application startup" - - - sleep 20 - - - - - echo "Checking HTTP" - - - curl --fail http://localhost:5000 - - - - echo "Application is running" From e3f9099a6b8d5b7aa035c8f9fd9a300a7214d818 Mon Sep 17 00:00:00 2001 From: romamatran Date: Fri, 10 Jul 2026 15:41:33 +0300 Subject: [PATCH 5/8] Add GitHub Actions workflow for production deployment --- .github/workflows/deploy-production.yml | 98 +++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 .github/workflows/deploy-production.yml diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml new file mode 100644 index 000000000..9a1d6a464 --- /dev/null +++ b/.github/workflows/deploy-production.yml @@ -0,0 +1,98 @@ +name: Deploy GranCaffe Production +on: + push: + branches: + - main + workflow_dispatch: +permissions: + contents: read + packages: write +env: + IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/grancaffe +jobs: + build-and-deploy: + name: Build Docker Image and Deploy + runs-on: ubuntu-latest + steps: + ################################### + # Checkout + ################################### + - name: Checkout source + uses: actions/checkout@v4 + ################################### + # Docker setup + ################################### + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + ################################### + # Login GHCR + ################################### + + - name: Login GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + ################################### + # Build and Push + ################################### + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + platforms: linux/amd64 + tags: | + ${{ env.IMAGE_NAME }}:latest + ${{ env.IMAGE_NAME }}:${{ github.sha }} + build-args: | + GIT_COMMIT=${{ github.sha }} + GIT_BRANCH=${{ github.ref_name }} + cache-from: + type=gha + cache-to: + type=gha,mode=max + ################################### + # Deploy DigitalOcean + ################################### + - name: Deploy to DigitalOcean + uses: appleboy/ssh-action@v1.2.0 + with: + host: ${{ secrets.DO_HOST }} + username: ${{ secrets.DO_USER }} + key: ${{ secrets.DO_SSH_KEY }} + script: | + set -e + echo "Go application folder" + cd /opt/grancaffe + echo "Login GHCR" + echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io \ + -u ${{ github.repository_owner }} \ + --password-stdin + echo "Pull latest image" + docker compose pull + echo "Restart services" + docker compose up -d --remove-orphans + echo "Cleanup old docker images" + docker image prune -f + echo "Deployment completed" + ################################### + # Verify + ################################### + - name: Health check + uses: appleboy/ssh-action@v1.2.0 + with: + host: ${{ secrets.DO_HOST }} + username: ${{ secrets.DO_USER }} + key: ${{ secrets.DO_SSH_KEY }} + script: | + set -e + echo "Containers status" + docker ps + echo "Wait application" + sleep 20 + echo "HTTP check" + curl --fail http://localhost:5000 + echo "GranCaffe is running" From 9591643d9ffa5185492c3c140c74469a5958e169 Mon Sep 17 00:00:00 2001 From: romamatran Date: Fri, 10 Jul 2026 15:42:57 +0300 Subject: [PATCH 6/8] Add pull request build workflow for Docker --- .github/workflows/pull-request-build.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/pull-request-build.yml diff --git a/.github/workflows/pull-request-build.yml b/.github/workflows/pull-request-build.yml new file mode 100644 index 000000000..c9efef1ed --- /dev/null +++ b/.github/workflows/pull-request-build.yml @@ -0,0 +1,24 @@ +name: Pull Request Build Test +on: + pull_request: + branches: + - main +permissions: + contents: read +jobs: + docker-build: + name: Docker Build Test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Build Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: false + tags: + grancaffe:test From e71a7042ba29a83341c8e5dd15dc2541cc5d90ac Mon Sep 17 00:00:00 2001 From: romamatran Date: Fri, 10 Jul 2026 15:55:35 +0300 Subject: [PATCH 7/8] Update deploy-production.yml --- .github/workflows/deploy-production.yml | 134 +++++++++--------------- 1 file changed, 51 insertions(+), 83 deletions(-) diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml index 9a1d6a464..7cdfed00a 100644 --- a/.github/workflows/deploy-production.yml +++ b/.github/workflows/deploy-production.yml @@ -11,88 +11,56 @@ env: IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/grancaffe jobs: build-and-deploy: - name: Build Docker Image and Deploy + name: Build and Deploy Production runs-on: ubuntu-latest steps: - ################################### - # Checkout - ################################### - - name: Checkout source - uses: actions/checkout@v4 - ################################### - # Docker setup - ################################### - - name: Setup Docker Buildx - uses: docker/setup-buildx-action@v3 - ################################### - # Login GHCR - ################################### - - - name: Login GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - ################################### - # Build and Push - ################################### - - name: Build and push Docker image - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile - push: true - platforms: linux/amd64 - tags: | - ${{ env.IMAGE_NAME }}:latest - ${{ env.IMAGE_NAME }}:${{ github.sha }} - build-args: | - GIT_COMMIT=${{ github.sha }} - GIT_BRANCH=${{ github.ref_name }} - cache-from: - type=gha - cache-to: - type=gha,mode=max - ################################### - # Deploy DigitalOcean - ################################### - - name: Deploy to DigitalOcean - uses: appleboy/ssh-action@v1.2.0 - with: - host: ${{ secrets.DO_HOST }} - username: ${{ secrets.DO_USER }} - key: ${{ secrets.DO_SSH_KEY }} - script: | - set -e - echo "Go application folder" - cd /opt/grancaffe - echo "Login GHCR" - echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io \ - -u ${{ github.repository_owner }} \ - --password-stdin - echo "Pull latest image" - docker compose pull - echo "Restart services" - docker compose up -d --remove-orphans - echo "Cleanup old docker images" - docker image prune -f - echo "Deployment completed" - ################################### - # Verify - ################################### - - name: Health check - uses: appleboy/ssh-action@v1.2.0 - with: - host: ${{ secrets.DO_HOST }} - username: ${{ secrets.DO_USER }} - key: ${{ secrets.DO_SSH_KEY }} - script: | - set -e - echo "Containers status" - docker ps - echo "Wait application" - sleep 20 - echo "HTTP check" - curl --fail http://localhost:5000 - echo "GranCaffe is running" + - name: Checkout repository + uses: actions/checkout@v4 + - name: Setup Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and Push Docker Image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + platforms: linux/amd64 + tags: | + ${{ env.IMAGE_NAME }}:latest + ${{ env.IMAGE_NAME }}:${{ github.sha }} + cache-from: | + type=gha + cache-to: | + type=gha,mode=max + - name: Deploy to DigitalOcean + uses: appleboy/ssh-action@v1.2.0 + with: + host: ${{ secrets.DO_HOST }} + username: ${{ secrets.DO_USER }} + key: ${{ secrets.DO_SSH_KEY }} + script: | + set -e + cd /opt/grancaffe + echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io \ + -u ${{ github.repository_owner }} \ + --password-stdin + docker compose pull + docker compose up -d --remove-orphans + docker image prune -f + - name: Verify deployment + uses: appleboy/ssh-action@v1.2.0 + with: + host: ${{ secrets.DO_HOST }} + username: ${{ secrets.DO_USER }} + key: ${{ secrets.DO_SSH_KEY }} + script: | + sleep 20 + docker ps + curl --fail http://localhost:5000 + echo "GranCaffe is running" From b1ad7330c30f24945f425330dd0bdfaf02d2f8e9 Mon Sep 17 00:00:00 2001 From: romamatran Date: Fri, 10 Jul 2026 16:07:54 +0300 Subject: [PATCH 8/8] Simplify Dockerfile build and publish steps Refactored Dockerfile to simplify build and publish stages by removing unnecessary loops for module and plugin builds. --- Dockerfile | 67 ++++++++++++++---------------------------------------- 1 file changed, 17 insertions(+), 50 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8eb075ebe..37b2e11f0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,51 +3,36 @@ # ========================== FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build-env - LABEL stage=build-env - WORKDIR /app +################################# +# Copy source +################################# COPY Directory.Packages.props . - COPY ./src/ ./ - - - ARG GIT_COMMIT ARG GIT_BRANCH +################################# +# Restore all dependencies +################################# - - -# Restore dependencies RUN dotnet restore /app/Web/Grand.Web/Grand.Web.csproj +################################# +# Build application +################################# - - -# Build modules -RUN for module in /app/Modules/*; do \ - dotnet build "$module" \ - -c Release \ - --no-restore \ - -p:SourceRevisionId=$GIT_COMMIT \ - -p:GitBranch=$GIT_BRANCH; \ -done - - - -# Build plugins -RUN for plugin in /app/Plugins/*; do \ - dotnet build "$plugin" \ +RUN dotnet build \ + /app/Web/Grand.Web/Grand.Web.csproj \ -c Release \ --no-restore \ -p:SourceRevisionId=$GIT_COMMIT \ - -p:GitBranch=$GIT_BRANCH; \ -done - - + -p:GitBranch=$GIT_BRANCH +################################# # Publish application +################################# RUN dotnet publish \ /app/Web/Grand.Web/Grand.Web.csproj \ @@ -57,38 +42,20 @@ RUN dotnet publish \ -p:SourceRevisionId=$GIT_COMMIT \ -p:GitBranch=$GIT_BRANCH - - # ========================== # Runtime stage # ========================== FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime - - WORKDIR /app - - EXPOSE 8080 - - - COPY --from=build-env /app/publish . - - -# IMPORTANT -# Verify dependencies exist - -RUN ls -la /app | grep AutoMapper || true - - +################################# +# Permissions +################################# RUN chown -R app:app /app - - USER app - - ENTRYPOINT ["dotnet","Grand.Web.dll"]