Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 0 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,3 @@ updates:
all-actions:
patterns:
- '*'

36 changes: 18 additions & 18 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,18 @@ jobs:
run: |
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
TAG="${{ steps.set-tag.outputs.tag }}"

echo "🏗️ Building image..."
docker build \
--build-arg COMMIT_SHA="${{ github.sha }}" \
--build-arg BRANCH="${{ github.ref_name }}" \
--build-arg BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
-t ${IMAGE}:${TAG} -t ${IMAGE}:latest .

echo "📤 Pushing image..."
docker push ${IMAGE}:${TAG}
docker push ${IMAGE}:latest

echo "✅ Image pushed successfully!"
echo "📦 Image: ${IMAGE}:${TAG}"
echo "📦 Image: ${IMAGE}:latest"
Expand All @@ -90,7 +90,7 @@ jobs:
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts

# Test SSH connection
echo "Testing SSH connection..."
ssh -i ~/.ssh/deploy_key -o StrictHostKeyChecking=no root@${{ secrets.SERVER_HOST }} "echo 'SSH connection successful'"
Expand All @@ -102,7 +102,7 @@ jobs:

echo "📦 Copying docker-compose.yml..."
scp -i ~/.ssh/deploy_key docker-compose.yml root@${{ secrets.SERVER_HOST }}:/opt/diffractwd-com/

echo "📦 Copying deployment script..."
scp -i ~/.ssh/deploy_key scripts/deploy.sh root@${{ secrets.SERVER_HOST }}:/opt/diffractwd-com/
ssh -i ~/.ssh/deploy_key root@${{ secrets.SERVER_HOST }} "chmod +x /opt/diffractwd-com/deploy.sh"
Expand All @@ -111,10 +111,10 @@ jobs:
id: deploy
run: |
IMAGE_TAG="${{ needs.build-and-push.outputs.image-tag }}"

echo "🚀 Deploying to production..."
echo "📦 Image tag: ${IMAGE_TAG}"

ssh -i ~/.ssh/deploy_key root@${{ secrets.SERVER_HOST }} << EOF
set -e
cd /opt/diffractwd-com
Expand Down Expand Up @@ -192,45 +192,45 @@ jobs:
const commitMessage = `${{ github.event.head_commit.message }}` || 'Manual deployment';
const eventName = '${{ github.event_name }}';
const triggerType = eventName === 'workflow_dispatch' ? 'Manual' : 'Automatic (push)';

let status = '✅ SUCCESS';
let emoji = '🎉';

if (buildResult === 'failure') {
status = '❌ FAILED - Build';
emoji = '🔨';
} else if (deployResult === 'failure') {
status = '❌ FAILED - Deployment';
emoji = '🚨';
}

const summary = `${emoji} **Deployment ${status}**

**Commit:** \`${commitSha.substring(0, 8)}\`
**Message:** ${commitMessage}
**Branch:** master
**Trigger:** ${triggerType}

**Pipeline Results:**
- 🐳 Build & Push: ${buildResult === 'success' ? '✅' : '❌'} ${buildResult}
- 🚀 Deployment: ${deployResult === 'success' ? '✅' : '❌'} ${deployResult}

**Details:**
- **Image Tag:** \`${imageTag}\`
- **Registry:** ghcr.io/vreshch/diffractwd.com
- **Server:** diffractwd.com
- **Deployment URL:** https://diffractwd.com

**Quick Actions:**
- 📋 [Workflow Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
- 🌐 [Visit Website](https://diffractwd.com)
- 📦 [Registry](https://github.com/${{ github.repository }}/pkgs/container/diffractwd.com)

---
⏰ Generated at: \`${new Date().toISOString()}\``;

console.log(summary);

// Create commit status
try {
await github.rest.repos.createCommitStatus({
Expand All @@ -244,4 +244,4 @@ jobs:
});
} catch (error) {
console.log('Could not create commit status:', error.message);
}
}
3 changes: 3 additions & 0 deletions .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ jobs:
- name: Lint code
run: npm run lint

- name: Format check
run: npm run format:check

- name: Build project
run: npm run build

Expand Down
40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ Website for the DiffractWD application — a free and open-source tool for powde

## Technologies

* React 19 & TypeScript
* Next.js 15 (App Router)
* Tailwind CSS 4
* Vitest & Playwright for testing
* Docker with Traefik reverse proxy
* GitHub Actions CI/CD
- React 19 & TypeScript
- Next.js 15 (App Router)
- Tailwind CSS 4
- Vitest & Playwright for testing
- Docker with Traefik reverse proxy
- GitHub Actions CI/CD

## Quick Start

Expand All @@ -26,18 +26,18 @@ npm run dev

## Available Scripts

| Command | Description |
|---|---|
| `npm run dev` | Start local development server |
| `npm run build` | Build for production |
| `npm start` | Start production server (port 3001) |
| `npm run lint` | Run ESLint |
| `npm run format` | Format code with Prettier |
| `npm test` | Run unit tests (Vitest) |
| `npm run test:watch` | Run unit tests in watch mode |
| `npm run test:e2e` | Run E2E tests (Playwright) |
| `npm run test:e2e:ui` | Run E2E tests with UI |
| `npm run verify` | Full verification (type check, lint, build, test) |
| Command | Description |
| --------------------- | ------------------------------------------------- |
| `npm run dev` | Start local development server |
| `npm run build` | Build for production |
| `npm start` | Start production server (port 3001) |
| `npm run lint` | Run ESLint |
| `npm run format` | Format code with Prettier |
| `npm test` | Run unit tests (Vitest) |
| `npm run test:watch` | Run unit tests in watch mode |
| `npm run test:e2e` | Run E2E tests (Playwright) |
| `npm run test:e2e:ui` | Run E2E tests with UI |
| `npm run verify` | Full verification (type check, lint, build, test) |

## Docker

Expand All @@ -52,5 +52,5 @@ Production deployment uses Docker Swarm with Traefik for automatic HTTPS.

## Contacts

* Website: [vreshch.com](https://vreshch.com)
* Email: vreshch@gmail.com
- Website: [vreshch.com](https://vreshch.com)
- Email: vreshch@gmail.com
16 changes: 8 additions & 8 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,40 @@ services:
- traefik.enable=true
- traefik.docker.network=traefik-public
- traefik.constraint-label=traefik-public

# HTTP Router (redirect to HTTPS, but allow ACME challenges)
- traefik.http.routers.diffractwd-http.rule=Host(`diffractwd.com`) || Host(`www.diffractwd.com`)
- traefik.http.routers.diffractwd-http.entrypoints=http
- traefik.http.routers.diffractwd-http.middlewares=https-redirect

# Create HTTPS redirect middleware that allows ACME challenges
- traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
- traefik.http.middlewares.https-redirect.redirectscheme.permanent=true

# HTTPS Router
- traefik.http.routers.diffractwd-https.rule=Host(`diffractwd.com`) || Host(`www.diffractwd.com`)
- traefik.http.routers.diffractwd-https.entrypoints=https
- traefik.http.routers.diffractwd-https.tls=true
- traefik.http.routers.diffractwd-https.tls.certresolver=letsencrypt

# Service configuration
- traefik.http.services.diffractwd.loadbalancer.server.port=3001

resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
cpus: '0.25'
memory: 128M

healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://127.0.0.1:3001/"]
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://127.0.0.1:3001/']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s

networks:
traefik-public:
external: true
external: true
2 changes: 1 addition & 1 deletion e2e/visual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export async function waitForVisualStability(page: Page, timeout = 500): Promise
export async function expectScreenshot(
page: Page,
name: string,
options: ScreenshotOptions = {},
options: ScreenshotOptions = {}
): Promise<void> {
const mode = getVisualMode();
const opts = { ...DEFAULT_OPTIONS, ...options };
Expand Down
22 changes: 14 additions & 8 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charSet="UTF-8" />
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta httpEquiv="X-UA-Compatible" content="IE=edge, chrome=1" />
<meta name="author" content="Volodymyr D. Vreshch" />
<meta name="description" content="DiffractWD - Free Open Source Software for Powder Diffraction Manipulation" />
<meta name="keywords" content="DiffractWD, Powder Diffraction Software, Powder Pattern Simulation, Powder Data Visualization, Free Software Download" />
</head>
<body>
<meta
name="description"
content="DiffractWD - Free Open Source Software for Powder Diffraction Manipulation"
/>
<meta
name="keywords"
content="DiffractWD, Powder Diffraction Software, Powder Pattern Simulation, Powder Data Visualization, Free Software Download"
/>
</head>
<body>
<div id="app"></div>
</body>
</body>
</html>
2 changes: 1 addition & 1 deletion public/manual/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html></html>
<html></html>
2 changes: 1 addition & 1 deletion public/screenshots/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<html></html>
<html></html>
22 changes: 16 additions & 6 deletions scripts/compare-screenshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ import pixelmatch from 'pixelmatch';

function listPngs(dir) {
if (!existsSync(dir)) return [];
return readdirSync(dir).filter((f) => f.endsWith('.png')).sort();
return readdirSync(dir)
.filter((f) => f.endsWith('.png'))
.sort();
}

function readPng(filepath) {
Expand Down Expand Up @@ -205,8 +207,12 @@ function generateHighlight(currentPath, diffImg, highlightPath) {
for (let x = x1; x <= x2; x++) {
const idx = (y * width + x) * 4;
highlight.data[idx] = Math.round(255 * fillAlpha + highlight.data[idx] * (1 - fillAlpha));
highlight.data[idx + 1] = Math.round(0 * fillAlpha + highlight.data[idx + 1] * (1 - fillAlpha));
highlight.data[idx + 2] = Math.round(255 * fillAlpha + highlight.data[idx + 2] * (1 - fillAlpha));
highlight.data[idx + 1] = Math.round(
0 * fillAlpha + highlight.data[idx + 1] * (1 - fillAlpha)
);
highlight.data[idx + 2] = Math.round(
255 * fillAlpha + highlight.data[idx + 2] * (1 - fillAlpha)
);
}
}
}
Expand All @@ -217,8 +223,12 @@ function generateHighlight(currentPath, diffImg, highlightPath) {
const idx = i * 4;
if (diffImg.data[idx + 3] > 0) {
highlight.data[idx] = Math.round(255 * pixelAlpha + currImg.data[idx] * (1 - pixelAlpha));
highlight.data[idx + 1] = Math.round(0 * pixelAlpha + currImg.data[idx + 1] * (1 - pixelAlpha));
highlight.data[idx + 2] = Math.round(255 * pixelAlpha + currImg.data[idx + 2] * (1 - pixelAlpha));
highlight.data[idx + 1] = Math.round(
0 * pixelAlpha + currImg.data[idx + 1] * (1 - pixelAlpha)
);
highlight.data[idx + 2] = Math.round(
255 * pixelAlpha + currImg.data[idx + 2] * (1 - pixelAlpha)
);
highlight.data[idx + 3] = 255;
}
}
Expand Down Expand Up @@ -263,7 +273,7 @@ function main() {

if (!baseDir || !currentDir) {
console.error(
'Usage: node compare-screenshots.js <base-dir> <current-dir> [--output file.json] [--diff-dir dir] [--highlight-dir dir]',
'Usage: node compare-screenshots.js <base-dir> <current-dir> [--output file.json] [--diff-dir dir] [--highlight-dir dir]'
);
process.exit(1);
}
Expand Down
Loading