diff --git a/.github/workflows/update-github-versions.yml b/.github/workflows/update-github-versions.yml new file mode 100644 index 000000000..a31299b84 --- /dev/null +++ b/.github/workflows/update-github-versions.yml @@ -0,0 +1,232 @@ +name: Update GitHub Versions + +on: + workflow_dispatch: + schedule: + # Runs 4x daily: 00:00, 06:00, 12:00, 18:00 UTC + - cron: "0 0,6,12,18 * * *" + +permissions: + contents: write + pull-requests: write + +env: + VERSIONS_FILE: frontend/public/json/github-versions.json + +jobs: + update-github-versions: + if: github.repository == 'community-scripts/ProxmoxVE' + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + ref: main + + - name: Generate GitHub App Token + id: generate-token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ vars.APP_ID }} + private-key: ${{ secrets.APP_PRIVATE_KEY }} + + - name: Extract GitHub versions from install scripts + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + run: | + set -euo pipefail + + echo "=========================================" + echo " Extracting GitHub versions from scripts" + echo "=========================================" + + # Initialize versions array + versions_json="[]" + + # Function to add a version entry + add_version() { + local slug="$1" + local repo="$2" + local version="$3" + local pinned="$4" + local date="$5" + + versions_json=$(echo "$versions_json" | jq \ + --arg slug "$slug" \ + --arg repo "$repo" \ + --arg version "$version" \ + --argjson pinned "$pinned" \ + --arg date "$date" \ + '. += [{"slug": $slug, "repo": $repo, "version": $version, "pinned": $pinned, "date": $date}]') + } + + # Get list of slugs from JSON files + echo "" + echo "=== Scanning JSON files for slugs ===" + + for json_file in frontend/public/json/*.json; do + [[ ! -f "$json_file" ]] && continue + + # Skip non-app JSON files + basename_file=$(basename "$json_file") + case "$basename_file" in + metadata.json|versions.json|github-versions.json|dependency-check.json|update-apps.json) + continue + ;; + esac + + # Extract slug from JSON + slug=$(jq -r '.slug // empty' "$json_file" 2>/dev/null) + [[ -z "$slug" ]] && continue + + # Find corresponding install script + install_script="install/${slug}-install.sh" + [[ ! -f "$install_script" ]] && continue + + echo -n "[$slug] " + + # Look for fetch_and_deploy_gh_release calls + # Pattern: fetch_and_deploy_gh_release "app" "owner/repo" ["mode"] ["version"] + while IFS= read -r line; do + # Skip commented lines + [[ "$line" =~ ^[[:space:]]*# ]] && continue + + # Extract repo and version from fetch_and_deploy_gh_release + if [[ "$line" =~ fetch_and_deploy_gh_release[[:space:]]+\"[^\"]*\"[[:space:]]+\"([^\"]+)\"([[:space:]]+\"([^\"]+)\")?([[:space:]]+\"([^\"]+)\")? ]]; then + repo="${BASH_REMATCH[1]}" + mode="${BASH_REMATCH[3]:-tarball}" + pinned_version="${BASH_REMATCH[5]:-latest}" + + # Check if version is pinned (not "latest" and not empty) + is_pinned=false + target_version="" + + if [[ -n "$pinned_version" && "$pinned_version" != "latest" ]]; then + is_pinned=true + target_version="$pinned_version" + echo -n "(pinned: $pinned_version) " + fi + + # Fetch version from GitHub + if [[ "$is_pinned" == "true" ]]; then + # For pinned versions, verify it exists and get date + response=$(gh api "repos/${repo}/releases/tags/${target_version}" 2>/dev/null || echo '{}') + if echo "$response" | jq -e '.tag_name' > /dev/null 2>&1; then + version=$(echo "$response" | jq -r '.tag_name') + date=$(echo "$response" | jq -r '.published_at // empty') + add_version "$slug" "$repo" "$version" "true" "$date" + echo "✓ $version (pinned)" + else + # Pinned version not found, skip + echo "⚠ pinned version $target_version not found" + fi + else + # Fetch latest release + response=$(gh api "repos/${repo}/releases/latest" 2>/dev/null || echo '{}') + if echo "$response" | jq -e '.tag_name' > /dev/null 2>&1; then + version=$(echo "$response" | jq -r '.tag_name') + date=$(echo "$response" | jq -r '.published_at // empty') + add_version "$slug" "$repo" "$version" "false" "$date" + echo "✓ $version" + else + # Try tags as fallback + version=$(gh api "repos/${repo}/tags" --jq '.[0].name // empty' 2>/dev/null || echo "") + if [[ -n "$version" ]]; then + add_version "$slug" "$repo" "$version" "false" "" + echo "✓ $version (from tags)" + else + echo "⚠ no version found" + fi + fi + fi + + break # Only first match per script + fi + done < <(grep 'fetch_and_deploy_gh_release' "$install_script" 2>/dev/null || true) + + done + + # Save versions file + echo "$versions_json" | jq --arg date "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ + '{generated: $date, versions: (. | sort_by(.slug))}' > "$VERSIONS_FILE" + + total=$(echo "$versions_json" | jq 'length') + echo "" + echo "=========================================" + echo " Total versions extracted: $total" + echo "=========================================" + + - name: Check for changes + id: check-changes + run: | + if git diff --quiet "$VERSIONS_FILE" 2>/dev/null; then + echo "changed=false" >> "$GITHUB_OUTPUT" + echo "No changes detected" + else + echo "changed=true" >> "$GITHUB_OUTPUT" + echo "Changes detected:" + git diff --stat "$VERSIONS_FILE" 2>/dev/null || true + fi + + - name: Create Pull Request + if: steps.check-changes.outputs.changed == 'true' + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} + run: | + BRANCH_NAME="automated/update-github-versions-$(date +%Y%m%d)" + + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "GitHub Actions[bot]" + + # Check if branch exists and delete it + git push origin --delete "$BRANCH_NAME" 2>/dev/null || true + + git checkout -b "$BRANCH_NAME" + git add "$VERSIONS_FILE" + git commit -m "chore: update github-versions.json + + Total versions: $(jq '.versions | length' "$VERSIONS_FILE") + Pinned versions: $(jq '[.versions[] | select(.pinned == true)] | length' "$VERSIONS_FILE") + Generated: $(jq -r '.generated' "$VERSIONS_FILE")" + + git push origin "$BRANCH_NAME" --force + + # Check if PR already exists + existing_pr=$(gh pr list --head "$BRANCH_NAME" --state open --json number --jq '.[0].number // empty') + + if [[ -n "$existing_pr" ]]; then + echo "PR #$existing_pr already exists, updating..." + else + gh pr create \ + --title "[Automated] Update GitHub versions" \ + --body "This PR updates version information from GitHub releases. + + ## How it works + 1. Scans all JSON files in \`frontend/public/json/\` for slugs + 2. Finds corresponding \`install/{slug}-install.sh\` scripts + 3. Extracts \`fetch_and_deploy_gh_release\` calls + 4. Fetches latest (or pinned) version from GitHub + + ## Stats + - Total versions: $(jq '.versions | length' "$VERSIONS_FILE") + - Pinned versions: $(jq '[.versions[] | select(.pinned == true)] | length' "$VERSIONS_FILE") + - Latest versions: $(jq '[.versions[] | select(.pinned == false)] | length' "$VERSIONS_FILE") + + --- + *Automatically generated from install scripts*" \ + --base main \ + --head "$BRANCH_NAME" \ + --label "automated pr" + fi + + - name: Auto-approve PR + if: steps.check-changes.outputs.changed == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + BRANCH_NAME="automated/update-github-versions-$(date +%Y%m%d)" + pr_number=$(gh pr list --head "$BRANCH_NAME" --state open --json number --jq '.[0].number') + if [[ -n "$pr_number" ]]; then + gh pr review "$pr_number" --approve + fi diff --git a/ct/dawarich.sh b/ct/dawarich.sh deleted file mode 100644 index e4ba70a28..000000000 --- a/ct/dawarich.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env bash -source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/misc/build.func) -# Copyright (c) 2021-2026 community-scripts ORG -# Author: MickLesk (CanbiZ) -# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE -# Source: https://github.com/Freika/dawarich - -APP="Dawarich" -var_tags="${var_tags:-location;tracking;gps}" -var_cpu="${var_cpu:-4}" -var_ram="${var_ram:-4096}" -var_disk="${var_disk:-15}" -var_os="${var_os:-debian}" -var_version="${var_version:-13}" -var_unprivileged="${var_unprivileged:-1}" - -header_info "$APP" -variables -color -catch_errors - -function update_script() { - header_info - check_container_storage - check_container_resources - - if [[ ! -d /opt/dawarich ]]; then - msg_error "No ${APP} Installation Found!" - exit - fi - - if check_for_gh_release "dawarich" "Freika/dawarich"; then - msg_info "Stopping Services" - systemctl stop dawarich-web dawarich-worker - msg_ok "Stopped Services" - - msg_info "Backing up Data" - cp -r /opt/dawarich/app/storage /opt/dawarich_storage_backup 2>/dev/null || true - cp /opt/dawarich/app/config/master.key /opt/dawarich_master.key 2>/dev/null || true - cp /opt/dawarich/app/config/credentials.yml.enc /opt/dawarich_credentials.yml.enc 2>/dev/null || true - msg_ok "Backed up Data" - - CLEAN_INSTALL=1 fetch_and_deploy_gh_release "dawarich" "Freika/dawarich" "tarball" "latest" "/opt/dawarich/app" - - RUBY_VERSION=$(cat /opt/dawarich/app/.ruby-version 2>/dev/null || echo "3.4.6") - RUBY_VERSION=${RUBY_VERSION} RUBY_INSTALL_RAILS="false" setup_ruby - - msg_info "Running Migrations" - cd /opt/dawarich/app - source /root/.profile - export PATH="/root/.rbenv/shims:/root/.rbenv/bin:$PATH" - eval "$(/root/.rbenv/bin/rbenv init - bash)" - - set -a && source /opt/dawarich/.env && set +a - - $STD bundle config set --local deployment 'true' - $STD bundle config set --local without 'development test' - $STD bundle install - - if [[ -f /opt/dawarich/package.json ]]; then - cd /opt/dawarich - $STD npm install - cd /opt/dawarich/app - elif [[ -f /opt/dawarich/app/package.json ]]; then - $STD npm install - fi - - $STD bundle exec rake assets:precompile - $STD bundle exec rails db:migrate - $STD bundle exec rake data:migrate - msg_ok "Ran Migrations" - - msg_info "Restoring Data" - cp -r /opt/dawarich_storage_backup/. /opt/dawarich/app/storage/ 2>/dev/null || true - cp /opt/dawarich_master.key /opt/dawarich/app/config/master.key 2>/dev/null || true - cp /opt/dawarich_credentials.yml.enc /opt/dawarich/app/config/credentials.yml.enc 2>/dev/null || true - rm -rf /opt/dawarich_storage_backup /opt/dawarich_master.key /opt/dawarich_credentials.yml.enc - msg_ok "Restored Data" - - msg_info "Starting Services" - systemctl start dawarich-web dawarich-worker - msg_ok "Started Services" - msg_ok "Updated successfully!" - fi - exit -} - -start -build_container -description - -msg_ok "Completed Successfully!\n" -echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" -echo -e "${INFO}${YW} Access it using the following URL:${CL}" -echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}" diff --git a/frontend/public/json/dawarich.json b/frontend/public/json/dawarich.json deleted file mode 100644 index 85659bdaa..000000000 --- a/frontend/public/json/dawarich.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "Dawarich", - "slug": "dawarich", - "categories": [ - 9 - ], - "date_created": "2026-01-16", - "type": "ct", - "updateable": true, - "privileged": false, - "interface_port": 3000, - "documentation": "https://dawarich.app/docs", - "website": "https://dawarich.app/", - "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/dawarich.webp", - "config_path": "/opt/dawarich/.env", - "description": "Dawarich is a self-hosted alternative to Google Timeline (Google Maps Location History). It allows you to import your location history from Google Maps Timeline and Owntracks, view it on a map, and analyze your location data with statistics and visualizations.", - "install_methods": [ - { - "type": "default", - "script": "ct/dawarich.sh", - "resources": { - "cpu": 4, - "ram": 4096, - "hdd": 15, - "os": "Debian", - "version": "13" - } - } - ], - "default_credentials": { - "username": "demo@dawarich.app", - "password": "password" - }, - "notes": [ - { - "text": "Default credentials: demo@dawarich.app / password - Change after first login!", - "type": "warning" - } - ] -} diff --git a/install/dawarich-install.sh b/install/dawarich-install.sh deleted file mode 100644 index 0adc17a14..000000000 --- a/install/dawarich-install.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) 2021-2026 community-scripts ORG -# Author: MickLesk (CanbiZ) -# License: MIT | https://github.com/community-scripts/ProxmoxVED/raw/main/LICENSE -# Source: https://github.com/Freika/dawarich - -source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" -color -verb_ip6 -catch_errors -setting_up_container -network_check -update_os - -msg_info "Installing Dependencies" -$STD apt install -y \ - build-essential \ - git \ - libpq-dev \ - libgeos-dev \ - libyaml-dev \ - libffi-dev \ - libssl-dev \ - libjemalloc2 \ - imagemagick \ - libmagickwand-dev \ - libvips-dev \ - cmake \ - redis-server \ - nginx -msg_ok "Installed Dependencies" - -PG_VERSION="17" PG_MODULES="postgis-3" setup_postgresql -PG_DB_NAME="dawarich_db" PG_DB_USER="dawarich" PG_DB_EXTENSIONS="postgis" setup_postgresql_db - -fetch_and_deploy_gh_release "dawarich" "Freika/dawarich" "tarball" "latest" "/opt/dawarich/app" - -msg_info "Setting up Directories" -mkdir -p /opt/dawarich/app/{storage,log,tmp/pids,tmp/cache,tmp/sockets} -msg_ok "Set up Directories" - -msg_info "Configuring Environment" -SECRET_KEY_BASE=$(openssl rand -hex 64) -RELEASE=$(get_latest_github_release "Freika/dawarich") -cat </opt/dawarich/.env -RAILS_ENV=production -SECRET_KEY_BASE=${SECRET_KEY_BASE} -DATABASE_HOST=localhost -DATABASE_USERNAME=${PG_DB_USER} -DATABASE_PASSWORD=${PG_DB_PASS} -DATABASE_NAME=${PG_DB_NAME} -REDIS_URL=redis://127.0.0.1:6379/0 -BACKGROUND_PROCESSING_CONCURRENCY=10 -APPLICATION_HOST=${LOCAL_IP} -APPLICATION_HOSTS=${LOCAL_IP},localhost -TIME_ZONE=UTC -DISABLE_TELEMETRY=true -APP_VERSION=${RELEASE} -EOF -msg_ok "Configured Environment" - -NODE_VERSION="22" setup_nodejs -RUBY_VERSION=$(cat /opt/dawarich/app/.ruby-version 2>/dev/null || echo "3.4.6") -RUBY_VERSION=${RUBY_VERSION} RUBY_INSTALL_RAILS="false" setup_ruby - -msg_info "Installing Dawarich" -cd /opt/dawarich/app -source /root/.profile -export PATH="/root/.rbenv/shims:/root/.rbenv/bin:$PATH" -eval "$(/root/.rbenv/bin/rbenv init - bash)" -set -a && source /opt/dawarich/.env && set +a -$STD gem install bundler -$STD bundle config set --local deployment 'true' -$STD bundle config set --local without 'development test' -$STD bundle install -if [[ -f /opt/dawarich/package.json ]]; then - cd /opt/dawarich - $STD npm install - cd /opt/dawarich/app -elif [[ -f /opt/dawarich/app/package.json ]]; then - $STD npm install -fi -$STD bundle exec rake assets:precompile -$STD bundle exec rails db:prepare -$STD bundle exec rake data:migrate -msg_ok "Installed Dawarich" - -msg_info "Creating Services" -cat </etc/systemd/system/dawarich-web.service -[Unit] -Description=Dawarich Web Server -After=network.target postgresql.service redis-server.service -Requires=postgresql.service redis-server.service - -[Service] -Type=simple -WorkingDirectory=/opt/dawarich/app -EnvironmentFile=/opt/dawarich/.env -ExecStart=/root/.rbenv/shims/bundle exec puma -C config/puma.rb -Restart=always -RestartSec=5 - -[Install] -WantedBy=multi-user.target -EOF - -cat </etc/systemd/system/dawarich-worker.service -[Unit] -Description=Dawarich Sidekiq Worker -After=network.target postgresql.service redis-server.service -Requires=postgresql.service redis-server.service - -[Service] -Type=simple -WorkingDirectory=/opt/dawarich/app -EnvironmentFile=/opt/dawarich/.env -ExecStart=/root/.rbenv/shims/bundle exec sidekiq -C config/sidekiq.yml -Restart=always -RestartSec=5 - -[Install] -WantedBy=multi-user.target -EOF - -systemctl enable -q --now redis-server dawarich-web dawarich-worker -msg_ok "Created Services" - -msg_info "Configuring Nginx" -cat </etc/nginx/sites-available/dawarich.conf -upstream dawarich { - server 127.0.0.1:3000; -} - -server { - listen 80; - server_name _; - - root /opt/dawarich/app/public; - client_max_body_size 100M; - - location ~ ^/(assets|packs)/ { - expires max; - add_header Cache-Control "public, immutable"; - try_files \$uri =404; - } - - location / { - try_files \$uri @rails; - } - - location @rails { - proxy_pass http://dawarich; - proxy_http_version 1.1; - proxy_set_header Host \$host; - proxy_set_header X-Real-IP \$remote_addr; - proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto \$scheme; - proxy_set_header Upgrade \$http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_redirect off; - proxy_buffering off; - } -} -EOF -ln -sf /etc/nginx/sites-available/dawarich.conf /etc/nginx/sites-enabled/ -rm -f /etc/nginx/sites-enabled/default -systemctl enable -q --now nginx -msg_ok "Configured Nginx" - -motd_ssh -customize -cleanup_lxc