Compare commits

...

8 Commits

Author SHA1 Message Date
Frank John Begornia
2a857d2bfa Add [TEST] and [CRON] labels to distinguish execution source
All checks were successful
Deploy Production Email Reports (Unified) / deploy (push) Successful in 1m0s
2026-01-04 13:56:14 +08:00
Frank John Begornia
2eeec4377f Send test emails to webmaster only during startup
All checks were successful
Deploy Production Email Reports (Unified) / deploy (push) Successful in 57s
2026-01-02 02:07:52 +08:00
Frank John Begornia
1c19c86205 Remove unused dbconfig.php include and add DNS resolution tests
All checks were successful
Deploy Production Email Reports (Unified) / deploy (push) Successful in 57s
2026-01-02 02:03:17 +08:00
Frank John Begornia
0ccda81dd7 Fix database connection to use TCP port instead of Unix socket
All checks were successful
Deploy Production Email Reports (Unified) / deploy (push) Successful in 57s
2026-01-02 02:00:30 +08:00
Frank John Begornia
c2ed5efab5 Add test emails for both brands on container startup
All checks were successful
Deploy Production Email Reports (Unified) / deploy (push) Successful in 57s
2026-01-02 01:57:22 +08:00
Frank John Begornia
3dcc7c4c6e Fix crond setpgid error by running in background with tail
All checks were successful
Deploy Production Email Reports (Unified) / deploy (push) Successful in 54s
2026-01-02 01:47:26 +08:00
Frank John Begornia
afa05d272e Add entrypoint script for better container startup and debugging
Some checks failed
Deploy Production Email Reports (Unified) / deploy (push) Failing after 18s
2026-01-02 01:44:36 +08:00
Frank John Begornia
0f75206307 Fix deployment: use pre-built image and fix workflow syntax
Some checks failed
Deploy Production Email Reports (Unified) / deploy (push) Failing after 23s
2026-01-02 01:41:57 +08:00
7 changed files with 145 additions and 22 deletions

View File

@@ -16,8 +16,10 @@ DB_PASS_MERCHBAY=your_merchbay_password
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
# Crew SMTP (mail@crewsportswear.com)
SMTP_PASS_CREW=your_crew_gmail_app_password
# Crew SMTP Account (mail@crewsportswear.com)
# Gmail App Password for: mail@crewsportswear.com
SMTP_PASS_CREW=
# MerchBay SMTP (support@merchbay.com)
SMTP_PASS_MERCHBAY=your_merchbay_gmail_app_password
# MerchBay SMTP Account (support@merchbay.com)
# Gmail App Password for: support@merchbay.com
SMTP_PASS_MERCHBAY=

View File

@@ -105,8 +105,21 @@ jobs:
echo "Starting unified container (env vars from .env file)"
docker compose up -d
echo "Waiting for container to start"
sleep 10
echo "Waiting for container to start (30 seconds)..."
sleep 5
# Check if container is running or restarting
CONTAINER_STATE=$(docker inspect --format='{{.State.Status}}' email_reports_unified 2>/dev/null || echo "not_found")
echo "Container state: $CONTAINER_STATE"
if [ "$CONTAINER_STATE" = "restarting" ]; then
echo "Container is restarting - showing logs:"
docker logs email_reports_unified
exit 1
fi
# Wait a bit more for initialization
sleep 25
if docker ps --format '{{.Names}}' | grep -q email_reports_unified; then
echo "✓ Container is running"
@@ -146,7 +159,8 @@ jobs:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
run: |
ssh -i ~/.ssh/id_ed25519 $DEPLOY_USER@$DEPLOY_HOST << 'EOF'
echo "Container status:"unified --format "table {{.Names}}\t{{.Status}}\t{{.State}}"
echo "Container status:"
docker ps --filter "name=email_reports_unified" --format "table {{.Names}}\t{{.Status}}\t{{.State}}"
echo ""
echo "Recent logs:"
@@ -163,6 +177,5 @@ jobs:
echo ""
echo "Filter by brand:"
echo " docker exec email_reports_unified grep '[CREW]' /app/email.log"
echo " docker exec email_reports_unified grep '[MERCHBAY]'
echo " docker exec email_reports_crew tail -f /app/email.log"
echo " docker exec email_reports_unified grep '[MERCHBAY]' /app/email.log"
EOF

View File

@@ -22,6 +22,10 @@ COPY . /app/
RUN mkdir -p /app/daily_order_reports_crew /app/daily_order_reports_merchbay && \
chmod 755 /app/daily_order_reports_crew /app/daily_order_reports_merchbay
# Copy entrypoint script
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
# Create crontab with both reports
RUN echo "55 23 * * * BRAND=crew php /app/send_report.php >> /var/log/cron.log 2>&1" > /etc/crontabs/root && \
echo "56 23 * * * BRAND=merchbay php /app/send_report.php >> /var/log/cron.log 2>&1" >> /etc/crontabs/root && \
@@ -35,5 +39,5 @@ RUN touch /var/log/cron.log && \
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD ps aux | grep -v grep | grep -q crond || exit 1
# Start cron in foreground
CMD crond -f -l 2
# Use entrypoint script
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@@ -150,6 +150,7 @@ The unified container handles both brands using the `BRAND` environment variable
**Crew Sportswear (`BRAND=crew`)**:
- Database: `custom_design`
- SMTP: `mail@crewsportswear.com`
- From: `orders@crewsportswear.com`
- To: `graphics@crewsportswear.com`
- BCC: webmaster, angelo, production @crewsportswear.com
@@ -158,12 +159,15 @@ The unified container handles both brands using the `BRAND` environment variable
**MerchBay (`BRAND=merchbay`)**:
- Database: `merchbay_laravel`
- SMTP: `support@merchbay.com`
- From: `orders@merchbay.com`
- To: `graphics@crewsportswear.com`
- BCC: webmaster, production @crewsportswear.com
- Admin: https://merchbay.app
- CSV: `daily_order_reports_merchbay/`
**Note**: Each brand uses its own Gmail account for SMTP authentication.
## Networks
Container must be on **crew-app-net** to access MySQL:

View File

@@ -1,8 +1,6 @@
version: '3.8'
services:
email-reports:
build: .
image: email_reports_unified:latest
container_name: email_reports_unified
restart: unless-stopped
environment:

90
docker-entrypoint.sh Normal file
View File

@@ -0,0 +1,90 @@
#!/bin/sh
set -e
echo "Email Reports Container Starting..."
echo "Current time: $(date)"
echo "Timezone: $(date +%Z)"
# Verify crontab is configured
echo ""
echo "Cron schedule:"
crontab -l || echo "Warning: No crontab found"
# Create log file if it doesn't exist
touch /var/log/cron.log
chmod 666 /var/log/cron.log
# Create email log if it doesn't exist
touch /app/email.log
chmod 666 /app/email.log
# Test PHP
echo ""
echo "Testing PHP..."
php -v || { echo "PHP test failed"; exit 1; }
# Test database connectivity (optional - won't fail if not reachable)
echo ""
echo "Environment variables loaded:"
echo " DB_HOST_CREW: ${DB_HOST_CREW:-not set}"
echo " DB_NAME_CREW: ${DB_NAME_CREW:-not set}"
echo " DB_USER_CREW: ${DB_USER_CREW:-not set}"
echo " DB_HOST_MERCHBAY: ${DB_HOST_MERCHBAY:-not set}"
echo " DB_NAME_MERCHBAY: ${DB_NAME_MERCHBAY:-not set}"
echo " DB_USER_MERCHBAY: ${DB_USER_MERCHBAY:-not set}"
echo " SMTP_HOST: ${SMTP_HOST:-not set}"
echo ""
# Test DNS resolution for database hosts
echo "Testing database host DNS resolution..."
if [ -n "${DB_HOST_CREW}" ]; then
echo -n " Crew DB (${DB_HOST_CREW}): "
getent hosts "${DB_HOST_CREW}" > /dev/null 2>&1 && echo "✓ Resolved" || echo "✗ Cannot resolve"
fi
if [ -n "${DB_HOST_MERCHBAY}" ]; then
echo -n " MerchBay DB (${DB_HOST_MERCHBAY}): "
getent hosts "${DB_HOST_MERCHBAY}" > /dev/null 2>&1 && echo "✓ Resolved" || echo "✗ Cannot resolve"
fi
echo ""
# Start crond in background
echo ""
echo "Starting cron daemon..."
echo "Logs will be written to:"
echo " - Cron output: /var/log/cron.log"
echo " - Email logs: /app/email.log"
echo ""
# Start crond in background
crond -l 2
# Verify crond started
sleep 2
if ! ps aux | grep -v grep | grep -q crond; then
echo "ERROR: crond failed to start"
exit 1
fi
echo "✓ Cron daemon is running"
echo ""
# Send test emails for both brands
echo "Sending test emails to verify configuration..."
echo ""
echo "[Testing Crew Sportswear]"
TEST_EMAIL=true BRAND=crew php /app/send_report.php
echo ""
echo "[Testing MerchBay]"
TEST_EMAIL=true BRAND=merchbay php /app/send_report.php
echo ""
echo "✓ Test emails sent to webmaster@crewsportswear.com"
echo ""
echo "Container is ready. Tailing logs..."
echo "Press Ctrl+C to stop (but don't - this keeps the container alive!)"
echo ""
# Keep container alive by tailing logs
tail -f /var/log/cron.log /app/email.log

View File

@@ -1,6 +1,6 @@
<?php
include 'dbconfig.php';
// dbconfig.php not needed - using environment variables directly
require("phpmailer/class.phpmailer.php");
date_default_timezone_set('America/Chicago');
$dateToday = date('Y-m-d');
@@ -8,12 +8,14 @@ $dateTimeToday = date("Y-m-d H:i:s");
// Determine which brand to process
$brand = getenv('BRAND') ?: 'crew'; // 'crew' or 'merchbay'
$is_test = getenv('TEST_EMAIL') === 'true';
// Brand-specific configuration
$config = [
'crew' => [
'db_name' => getenv('DB_NAME_CREW') ?: 'custom_design',
'db_host' => getenv('DB_HOST_CREW') ?: getenv('DB_HOST') ?: 'mysql',
'db_port' => getenv('DB_PORT_CREW') ?: '3306',
'db_user' => getenv('DB_USER_CREW') ?: 'crew_user',
'db_pass' => getenv('DB_PASS_CREW') ?: getenv('DB_PASS'),
'smtp_user' => 'mail@crewsportswear.com',
@@ -30,6 +32,7 @@ $config = [
'merchbay' => [
'db_name' => getenv('DB_NAME_MERCHBAY') ?: 'merchbay_laravel',
'db_host' => getenv('DB_HOST_MERCHBAY') ?: getenv('DB_HOST') ?: 'mysql',
'db_port' => getenv('DB_PORT_MERCHBAY') ?: '3306',
'db_user' => getenv('DB_USER_MERCHBAY') ?: 'merchbay_user',
'db_pass' => getenv('DB_PASS_MERCHBAY') ?: getenv('DB_PASS'),
'smtp_user' => 'support@merchbay.com',
@@ -50,7 +53,7 @@ $cfg = $config[$brand];
// Connect to brand-specific database
try {
$conn = new PDO(
"mysql:host={$cfg['db_host']};dbname={$cfg['db_name']}",
"mysql:host={$cfg['db_host']};port={$cfg['db_port']};dbname={$cfg['db_name']}",
$cfg['db_user'],
$cfg['db_pass']
);
@@ -127,10 +130,16 @@ if($result > 0){
$mail->Password = $cfg['smtp_pass'];
$mail->SetFrom($cfg['email_from'], $cfg['email_from_name']);
$mail->addAddress($cfg['email_to']);
foreach ($cfg['email_bcc'] as $bcc) {
$mail->addBCC($bcc);
// Check if this is a test email (override recipients)
$test_mode = getenv('TEST_EMAIL') === 'true';
if ($test_mode) {
$mail->addAddress('webmaster@crewsportswear.com');
} else {
$mail->addAddress($cfg['email_to']);
foreach ($cfg['email_bcc'] as $bcc) {
$mail->addBCC($bcc);
}
}
$mail->addAttachment($filename);
@@ -141,14 +150,17 @@ if($result > 0){
$mail->IsHTML(true);
if(!$mail->Send()){
$msg = $dateTimeToday . "\t\t\t{$cfg['log_prefix']} Mailer Error: " . $mail->ErrorInfo . "\n";
$test_label = $is_test ? ' [TEST]' : ' [CRON]';
$msg = $dateTimeToday . "\t\t\t{$cfg['log_prefix']}{$test_label} Mailer Error: " . $mail->ErrorInfo . "\n";
file_put_contents('email.log', print_r($msg, true), FILE_APPEND);
} else {
$msg = $dateTimeToday . "\t\t\t{$cfg['log_prefix']} successfully sent ({$result} orders)\n";
$test_label = $is_test ? ' [TEST]' : ' [CRON]';
$msg = $dateTimeToday . "\t\t\t{$cfg['log_prefix']}{$test_label} successfully sent ({$result} orders)\n";
file_put_contents('email.log', print_r($msg, true), FILE_APPEND);
}
} else {
$msg = $dateTimeToday . "\t\t\t{$cfg['log_prefix']} No order for today\n";
$test_label = $is_test ? ' [TEST]' : ' [CRON]';
$msg = $dateTimeToday . "\t\t\t{$cfg['log_prefix']}{$test_label} No order for today\n";
file_put_contents('email.log', print_r($msg, true), FILE_APPEND);
}