14 Commits

Author SHA1 Message Date
efc9e5c3dd updating virustotal to v3 endpoints
All checks were successful
Build and Release to Staging / Build Vision Start (push) Successful in 7s
Build and Release / build (push) Successful in 38s
Build and Release to Staging / Build Vision Start Image (push) Successful in 1m15s
Build and Release to Staging / Deploy Vision Start (staging) (push) Successful in 3s
Build and Release / virus-total-check (push) Successful in 49s
Build and Release / release (push) Successful in 5s
Build and Release / Build Vision Start Image (push) Successful in 1m1s
Build and Release / Deploy Vision Start (production) (push) Successful in 3s
2026-03-21 00:59:49 -03:00
65c6946e7f adjusting intervals
Some checks failed
Build and Release to Staging / Build Vision Start (push) Successful in 7s
Build and Release / build (push) Successful in 8s
Build and Release to Staging / Build Vision Start Image (push) Successful in 1m2s
Build and Release / virus-total-check (push) Failing after 37s
Build and Release / release (push) Has been skipped
Build and Release / Build Vision Start Image (push) Has been skipped
Build and Release / Deploy Vision Start (production) (push) Has been skipped
Build and Release to Staging / Deploy Vision Start (staging) (push) Successful in 3s
2026-03-21 00:48:25 -03:00
3129fa6531 Merge branch 'main' of git.ivanch.me:ivanch/vision-start
Some checks failed
Build and Release to Staging / Build Vision Start (push) Successful in 7s
Build and Release to Staging / Build Vision Start Image (push) Successful in 1m3s
Build and Release to Staging / Deploy Vision Start (staging) (push) Successful in 9s
Build and Release / build (push) Successful in 16s
Build and Release / virus-total-check (push) Failing after 1m7s
Build and Release / release (push) Has been skipped
Build and Release / Build Vision Start Image (push) Has been skipped
Build and Release / Deploy Vision Start (production) (push) Has been skipped
2026-03-21 00:38:04 -03:00
82da27cf8d fixing release pipeline (final ;)) 2026-03-21 00:38:00 -03:00
c4dce04d42 migrate to Preact and add animations (#1)
All checks were successful
Build and Release to Staging / Build Vision Start (push) Successful in 8s
Build and Release to Staging / Build Vision Start Image (push) Successful in 1m1s
Build and Release to Staging / Deploy Vision Start (staging) (push) Successful in 3s
- Replace React 19 with Preact via @preact/preset-vite (zero component changes needed — Vite aliases react → preact/compat at build time)
- Add custom iOS easing curves (ease-ios, ease-spring) via Tailwind @theme
- Update all transitions to use iOS-standard 200ms durations and spring/decel easing
- Add active:scale press feedback on tiles, buttons, and toggles
- Toggle knob now uses spring easing for a satisfying snap

Reviewed-on: #1
Co-authored-by: Jose Henrique <jose.henrique.ivan@gmail.com>
Co-committed-by: Jose Henrique <jose.henrique.ivan@gmail.com>
2026-03-21 03:32:01 +00:00
c2b3356022 trying ubuntu-amd64
All checks were successful
Build and Release to Staging / Build Vision Start (push) Successful in 11s
Build and Release to Staging / Build Vision Start Image (push) Successful in 2m28s
Build and Release to Staging / Deploy Vision Start (staging) (push) Successful in 8s
2026-03-21 00:25:25 -03:00
d067e0b95c try
Some checks failed
Build and Release to Staging / Build Vision Start (push) Successful in 11s
Build and Release to Staging / Build Vision Start Image (push) Failing after 3m29s
Build and Release to Staging / Deploy Vision Start (staging) (push) Has been skipped
2026-03-21 00:16:32 -03:00
aec7a331c6 maybe now
Some checks failed
Build and Release to Staging / Build Vision Start (push) Successful in 11s
Build and Release to Staging / Build Vision Start Image (push) Failing after 1m32s
Build and Release to Staging / Deploy Vision Start (staging) (push) Has been skipped
2026-03-20 23:49:30 -03:00
0d636ab680 another try
Some checks failed
Build and Release to Staging / Build Vision Start (push) Successful in 11s
Build and Release to Staging / Build Vision Start Image (push) Failing after 1m32s
Build and Release to Staging / Deploy Vision Start (staging) (push) Has been skipped
2026-03-20 23:46:29 -03:00
69c6c6fe09 maybe fixing pipeline docker
Some checks failed
Build and Release to Staging / Build Vision Start (push) Successful in 11s
Build and Release to Staging / Build Vision Start Image (push) Failing after 2m11s
Build and Release to Staging / Deploy Vision Start (staging) (push) Has been skipped
2026-03-20 23:37:41 -03:00
fd552c48cd fixing pipelines
Some checks failed
Build and Release to Staging / Build Vision Start (push) Successful in 11s
Build and Release to Staging / Build Vision Start Image (push) Failing after 1m35s
Build and Release to Staging / Deploy Vision Start (staging) (push) Has been skipped
2026-03-20 23:31:30 -03:00
95b7be5219 fixing both pipelines
Some checks failed
Build and Release to Staging / Build Vision Start (push) Successful in 12s
Build and Release to Staging / Deploy Vision Start (staging) (push) Has been cancelled
Build and Release to Staging / Build Vision Start Image (push) Has been cancelled
2026-03-20 23:27:41 -03:00
b8e1468a46 adding dockerfile and pipelines
Some checks failed
Build and Release to Staging / Build Vision Start (push) Successful in 50s
Build and Release to Staging / Deploy Vision Start (staging) (push) Has been cancelled
Build and Release to Staging / Build Vision Start Image (push) Has been cancelled
2026-03-20 23:26:18 -03:00
199d92f733 updating .gitignore 2026-03-20 23:14:32 -03:00
6 changed files with 161 additions and 40 deletions

6
.dockerignore Normal file
View File

@@ -0,0 +1,6 @@
node_modules
dist
.git
.env
.DS_Store
.claude/

View File

@@ -1,14 +1,22 @@
name: Build and Release name: Build and Release to Staging
on: on:
push: push:
branches: branches:
- main - main
workflow_dispatch:
env:
REGISTRY_HOST: git.ivanch.me
REGISTRY_USERNAME: ivanch
IMAGE_NAME: ${{ env.REGISTRY_HOST }}/ivanch/vision-start
IMAGE_TAG: staging
jobs: jobs:
build: build:
name: Build Vision Start
if: gitea.event_name == 'push' if: gitea.event_name == 'push'
runs-on: ubuntu-latest runs-on: ubuntu-amd64
steps: steps:
- name: Check out repository code - name: Check out repository code
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -16,3 +24,47 @@ jobs:
run: npm install run: npm install
- name: Run build - name: Run build
run: npm run build run: npm run build
build_vision_start:
name: Build Vision Start Image
runs-on: ubuntu-amd64
needs: build
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Log in to Container Registry
run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" \
| docker login "${{ env.REGISTRY_HOST }}" \
-u "${{ env.REGISTRY_USERNAME }}" \
--password-stdin
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and Push Multi-Arch Image
uses: docker/build-push-action@v6
with:
push: true
context: .
platforms: linux/amd64,linux/arm64
tags: |
${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
deploy_vision_start:
name: Deploy Vision Start (staging)
runs-on: ubuntu-amd64
needs: build_vision_start
steps:
- name: Recreate Container
uses: appleboy/ssh-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
script: |
cd ${{ secrets.STAGING_DIR }}
docker compose pull
docker compose up -d --force-recreate

View File

@@ -5,6 +5,12 @@ on:
tags: tags:
- v* - v*
env:
REGISTRY_HOST: git.ivanch.me
REGISTRY_USERNAME: ivanch
IMAGE_NAME: ${{ env.REGISTRY_HOST }}/ivanch/vision-start
IMAGE_TAG: latest
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -53,8 +59,9 @@ jobs:
virustotal_apikey: ${{ secrets.VIRUSTOTAL_APIKEY }} virustotal_apikey: ${{ secrets.VIRUSTOTAL_APIKEY }}
VIRUS_TOTAL_FILE: vision-start-${{ gitea.ref_name }}.zip VIRUS_TOTAL_FILE: vision-start-${{ gitea.ref_name }}.zip
run: | run: |
# Run the VirusTotal check script and capture output # Run the VirusTotal check script and capture output in real-time
bash scripts/check_virustotal.sh > vt_output.txt 2>&1 set -o pipefail
bash scripts/check_virustotal.sh 2>&1 | tee vt_output.txt
# Extract analysis URL and detection ratio from output # Extract analysis URL and detection ratio from output
ANALYSIS_URL=$(grep "Analysis URL:" vt_output.txt | cut -d' ' -f3- || echo "Not available") ANALYSIS_URL=$(grep "Analysis URL:" vt_output.txt | cut -d' ' -f3- || echo "Not available")
@@ -64,9 +71,6 @@ jobs:
echo "analysis-url=$ANALYSIS_URL" >> $GITEA_OUTPUT echo "analysis-url=$ANALYSIS_URL" >> $GITEA_OUTPUT
echo "detection-ratio=$DETECTION_RATIO" >> $GITEA_OUTPUT echo "detection-ratio=$DETECTION_RATIO" >> $GITEA_OUTPUT
# Display the full output
cat vt_output.txt
release: release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [build, virus-total-check] needs: [build, virus-total-check]
@@ -88,3 +92,47 @@ jobs:
name: ${{ gitea.ref_name }} name: ${{ gitea.ref_name }}
tag_name: ${{ gitea.ref_name }} tag_name: ${{ gitea.ref_name }}
files: vision-start-${{ gitea.ref_name }}.zip files: vision-start-${{ gitea.ref_name }}.zip
build_vision_start:
name: Build Vision Start Image
runs-on: ubuntu-amd64
needs: [build, virus-total-check]
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Log in to Container Registry
run: |
echo "${{ secrets.REGISTRY_PASSWORD }}" \
| docker login "${{ env.REGISTRY_HOST }}" \
-u "${{ env.REGISTRY_USERNAME }}" \
--password-stdin
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and Push Multi-Arch Image
uses: docker/build-push-action@v6
with:
push: true
context: .
platforms: linux/amd64,linux/arm64
tags: |
${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}
deploy_vision_start:
name: Deploy Vision Start (production)
runs-on: ubuntu-amd64
needs: build_vision_start
steps:
- name: Recreate Container
uses: appleboy/ssh-action@v0.1.7
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
port: ${{ secrets.PORT }}
script: |
cd ${{ secrets.PROD_DIR }}
docker compose pull
docker compose up -d --force-recreate

1
.gitignore vendored
View File

@@ -11,6 +11,7 @@ node_modules
dist dist
dist-ssr dist-ssr
*.local *.local
.claude/
# Editor directories and files # Editor directories and files
.vscode/* .vscode/*

14
Dockerfile Normal file
View File

@@ -0,0 +1,14 @@
FROM node:22-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN sh scripts/prepare_release.sh
RUN npm run build
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY manifest.json /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -9,7 +9,7 @@ set -e
# Configuration # Configuration
FILE_PATH="${VIRUS_TOTAL_FILE:-vision-start.zip}" FILE_PATH="${VIRUS_TOTAL_FILE:-vision-start.zip}"
API_KEY="${virustotal_apikey}" API_KEY="${virustotal_apikey}"
BASE_URL="https://www.virustotal.com/vtapi/v2" BASE_URL="https://www.virustotal.com/api/v3"
# Check if API key is set # Check if API key is set
if [ -z "$API_KEY" ]; then if [ -z "$API_KEY" ]; then
@@ -38,12 +38,12 @@ echo "Uploading $FILE_PATH to VirusTotal for analysis..."
# Upload file to VirusTotal # Upload file to VirusTotal
UPLOAD_RESPONSE=$(curl -s -X POST \ UPLOAD_RESPONSE=$(curl -s -X POST \
-F "apikey=$API_KEY" \ -H "x-apikey: $API_KEY" \
-F "file=@$FILE_PATH" \ -F "file=@$FILE_PATH" \
"$BASE_URL/file/scan") "$BASE_URL/files")
# Extract scan_id from response # Extract scan_id from response
SCAN_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.scan_id') SCAN_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.data.id')
if [ "$SCAN_ID" == "null" ] || [ -z "$SCAN_ID" ]; then if [ "$SCAN_ID" == "null" ] || [ -z "$SCAN_ID" ]; then
echo "Error: Failed to upload file or get scan ID" echo "Error: Failed to upload file or get scan ID"
@@ -55,7 +55,7 @@ echo "File uploaded successfully. Scan ID: $SCAN_ID"
echo "Waiting for analysis to complete..." echo "Waiting for analysis to complete..."
# Wait for analysis to complete and get results # Wait for analysis to complete and get results
MAX_ATTEMPTS=30 MAX_ATTEMPTS=60
ATTEMPT=0 ATTEMPT=0
SLEEP_INTERVAL=10 SLEEP_INTERVAL=10
@@ -63,40 +63,40 @@ while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
echo "Checking analysis status (attempt $((ATTEMPT + 1))/$MAX_ATTEMPTS)..." echo "Checking analysis status (attempt $((ATTEMPT + 1))/$MAX_ATTEMPTS)..."
# Get scan report # Get scan report
REPORT_RESPONSE=$(curl -s -X POST \ REPORT_RESPONSE=$(curl -s -X GET \
-d "apikey=$API_KEY" \ -H "x-apikey: $API_KEY" \
-d "resource=$SCAN_ID" \ "$BASE_URL/analyses/$SCAN_ID")
"$BASE_URL/file/report")
# Check if analysis is complete # Check if analysis is complete
RESPONSE_CODE=$(echo "$REPORT_RESPONSE" | jq -r '.response_code') RESPONSE_CODE=$(echo "$REPORT_RESPONSE" | jq -r '.data.attributes.status')
if [ "$RESPONSE_CODE" == "1" ]; then if [ "$RESPONSE_CODE" == "completed" ]; then
# Analysis complete # Analysis complete
echo "Analysis completed!" echo "Analysis completed!"
# Extract results # Extract results
POSITIVES=$(echo "$REPORT_RESPONSE" | jq -r '.positives') POSITIVES=$(echo "$REPORT_RESPONSE" | jq -r '.data.attributes.stats.malicious')
TOTAL=$(echo "$REPORT_RESPONSE" | jq -r '.total') SUSPICIOUS=$(echo "$REPORT_RESPONSE" | jq -r '.data.attributes.stats.suspicious')
PERMALINK=$(echo "$REPORT_RESPONSE" | jq -r '.permalink') # The v3 analyses object has no 'total' field — compute it by summing all stat categories
TOTAL=$(echo "$REPORT_RESPONSE" | jq '[.data.attributes.stats | to_entries[].value] | add')
ANALYSIS_ID=$(echo "$REPORT_RESPONSE" | jq -r '.data.id')
PERMALINK="https://www.virustotal.com/gui/file-analysis/${ANALYSIS_ID}"
echo "Analysis URL: $PERMALINK" echo "Analysis URL: $PERMALINK"
echo "Detection ratio: $POSITIVES/$TOTAL" echo "Detection ratio: $POSITIVES/$TOTAL"
# Check if file is safe # Check if file is safe
if [ "$POSITIVES" -eq 0 ]; then if [ "$POSITIVES" -eq 0 ] && [ "$SUSPICIOUS" -eq 0 ]; then
echo "✅ File is clean (no threats detected)" echo "✅ File is clean (no threats detected)"
exit 0 exit 0
else else
echo "❌ File contains threats ($POSITIVES detections out of $TOTAL scanners)" echo "❌ File flagged: $POSITIVES malicious, $SUSPICIOUS suspicious (out of $TOTAL scanners)"
exit 1 exit 1
fi fi
elif [ "$RESPONSE_CODE" == "0" ]; then elif [ "$RESPONSE_CODE" == "queued" ]; then
# File not found or analysis not complete yet
echo "Analysis still in progress..."
elif [ "$RESPONSE_CODE" == "-2" ]; then
# Still queued for analysis
echo "File still queued for analysis..." echo "File still queued for analysis..."
elif [ "$RESPONSE_CODE" == "in-progress" ]; then
echo "Analysis still in progress..."
else else
echo "Unexpected response code: $RESPONSE_CODE" echo "Unexpected response code: $RESPONSE_CODE"
echo "Response: $REPORT_RESPONSE" echo "Response: $REPORT_RESPONSE"