Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a7250d3
Add GitHub Actions workflow for production deployment
romamatran Jul 10, 2026
6e80a31
Add SSH connection test workflow
romamatran Jul 10, 2026
9e82be6
Enhance Docker deployment workflow
romamatran Jul 10, 2026
da38778
Rename workflow to Deploy GranCaffe and update steps
romamatran Jul 10, 2026
8857698
Update deploy-production.yml
romamatran Jul 10, 2026
3cf9bb7
Update deploy-production.yml
romamatran Jul 10, 2026
be5a36c
Update docker-image.yml
romamatran Jul 10, 2026
6119657
Refactor GitHub Actions for GranCaffe deployment
romamatran Jul 10, 2026
171b0c1
Update deploy-production.yml
romamatran Jul 10, 2026
1d36f66
Update Dockerfile
romamatran Jul 10, 2026
8521abe
Delete .github/workflows/grandnode.yml
romamatran Jul 10, 2026
3766501
Delete .github/workflows/docker-image-pr.yml
romamatran Jul 10, 2026
a74ff80
Delete .github/workflows/docker-image.yml
romamatran Jul 10, 2026
589c856
Delete .github/workflows/test-ssh.yml
romamatran Jul 10, 2026
c6b863d
Delete .github/workflows/deploy-production.yml
romamatran Jul 10, 2026
e3f9099
Add GitHub Actions workflow for production deployment
romamatran Jul 10, 2026
9591643
Add pull request build workflow for Docker
romamatran Jul 10, 2026
e71a704
Update deploy-production.yml
romamatran Jul 10, 2026
b1ad733
Simplify Dockerfile build and publish steps
romamatran Jul 10, 2026
1f2170d
fix(sitemap): remove backslash from the front in url for sitemap values
Jul 10, 2026
968cd91
Refactor Dockerfile to include build arguments and directories
romamatran Jul 10, 2026
8cb837d
Update docker-image-pr.yml
romamatran Jul 10, 2026
065c05f
Merge branch 'develop'
Jul 10, 2026
b51e694
feat(scheduled task): enable scheduled task module
Jul 10, 2026
795405c
dev to main
Jul 10, 2026
09bafee
Merge pull request #2 from romamatran/main
romamatran Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .github/workflows/deploy-production.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
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 and Deploy Production
runs-on: ubuntu-latest
steps:
- 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/[email protected]
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/[email protected]
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"
22 changes: 1 addition & 21 deletions .github/workflows/docker-image-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,26 +68,6 @@ jobs:
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 ==="
Expand All @@ -98,4 +78,4 @@ jobs:
- name: Stop and remove the container
run: |
docker stop grandnode2-container
docker rm grandnode2-container
docker rm grandnode2-container
53 changes: 0 additions & 53 deletions .github/workflows/docker-image.yml

This file was deleted.

75 changes: 0 additions & 75 deletions .github/workflows/grandnode.yml

This file was deleted.

24 changes: 24 additions & 0 deletions .github/workflows/pull-request-build.yml
Original file line number Diff line number Diff line change
@@ -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
60 changes: 37 additions & 23 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,36 +1,50 @@
# ==========================
# Build stage
# ==========================
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build-env
LABEL stage=build-env
WORKDIR /app
ARG GIT_COMMIT=local
ARG GIT_BRANCH=local
# Copy source
COPY Directory.Packages.props .
COPY ./src/ ./

# Restore
RUN dotnet restore /app/Web/Grand.Web/Grand.Web.csproj
#################################
# Build application
#################################

# Publish application
RUN dotnet publish \
/app/Web/Grand.Web/Grand.Web.csproj \
-c Release \
-o /app/publish \
--no-restore \
-p:SourceRevisionId=$GIT_COMMIT \
-p:GitBranch=$GIT_BRANCH


# ==========================
# Runtime stage
# ==========================

# Copy
COPY Directory.Packages.props /app/
COPY ./src/ /app/

ARG GIT_COMMIT
ARG GIT_BRANCH

# Build modules
RUN for module in /app/Modules/*; do \
dotnet build "$module" -c Release -p:SourceRevisionId=$GIT_COMMIT -p:GitBranch=$GIT_BRANCH; \
done
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime

# Build plugins
RUN for plugin in /app/Plugins/*; do \
dotnet build "$plugin" -c Release -p:SourceRevisionId=$GIT_COMMIT -p:GitBranch=$GIT_BRANCH; \
done
WORKDIR /app

# Publish Web project
RUN dotnet publish /app/Web/Grand.Web/Grand.Web.csproj -c Release -o ./build/release -p:SourceRevisionId=$GIT_COMMIT -p:GitBranch=$GIT_BRANCH
EXPOSE 8080

# Runtime stage
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
COPY --from=build-env /app/publish .

EXPOSE 8080
WORKDIR /app
COPY --from=build-env /app/build/release .
# Ensure runtime folders exist
RUN mkdir -p /app/App_Data \
&& mkdir -p /app/App_Data/DataProtectionKeys \
&& mkdir -p /app/wwwroot

RUN chown -R app:app /app/App_Data /app/wwwroot /app/Plugins
# Give ownership to the non-root user
RUN chown -R app:app /app

USER app

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,31 @@ private IEnumerable<SitemapUrl> GetCustomUrls()
var storeLocation = GetStoreLocation();

return _commonSettings.SitemapCustomUrls.Select(customUrl =>
new SitemapUrl(string.Concat(storeLocation, customUrl), string.Empty, UpdateFrequency.Weekly,
DateTime.UtcNow));
{
// Use proper URI composition to handle path joining correctly
// This avoids malformed URLs with leading slashes before scheme (e.g., "/https://")
if (string.IsNullOrEmpty(customUrl))
return new SitemapUrl(storeLocation, string.Empty, UpdateFrequency.Weekly, DateTime.UtcNow);

// Check if customUrl is already an absolute URL (contains ://)
if (customUrl.Contains("://"))
return new SitemapUrl(customUrl, string.Empty, UpdateFrequency.Weekly, DateTime.UtcNow);

// For relative URLs, use Uri to properly combine the paths
try
{
var baseUri = new Uri(storeLocation);
var combinedUri = new Uri(baseUri, customUrl);
return new SitemapUrl(combinedUri.ToString(), string.Empty, UpdateFrequency.Weekly, DateTime.UtcNow);
}
catch
{
// Fallback to simple concatenation if Uri construction fails
// Ensure proper path separator
var separator = storeLocation.EndsWith("/") || customUrl.StartsWith("/") ? "" : "/";
return new SitemapUrl(string.Concat(storeLocation, separator, customUrl), string.Empty, UpdateFrequency.Weekly, DateTime.UtcNow);
}
});
}

private string XmlEncode(string str)
Expand Down
2 changes: 1 addition & 1 deletion src/Web/Grand.Web.Admin/App_Data/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
"FeatureManagement": {
"Grand.Module.Installer": false,
"Grand.Module.Migration": false,
"Grand.Module.ScheduledTasks": false,
"Grand.Module.ScheduledTasks": true,
"Grand.Module.Api": false
},
"Redis": {
Expand Down