diff --git a/.github/actions/calculate-version/action.yml b/.github/actions/calculate-version/action.yml index 740f6f25..b85f6a87 100644 --- a/.github/actions/calculate-version/action.yml +++ b/.github/actions/calculate-version/action.yml @@ -24,8 +24,9 @@ inputs: description: 'Deploy to Apple App Store' required: false default: 'false' + # DISABLED: AppImage requires system WebKit2GTK - not truly portable deploy-appimage: - description: 'Build AppImage' + description: 'Build AppImage (DISABLED)' required: false default: 'false' deploy-linux-terminal: @@ -61,9 +62,10 @@ outputs: deploy-apple: description: 'Deploy Apple flag' value: ${{ steps.stores.outputs.deploy-apple }} + # DISABLED: AppImage builds disabled deploy-appimage: - description: 'Deploy AppImage flag' - value: ${{ steps.stores.outputs.deploy-appimage }} + description: 'Deploy AppImage flag (DISABLED)' + value: 'false' deploy-linux-terminal: description: 'Deploy Linux Terminal flag' value: ${{ steps.stores.outputs.deploy-linux-terminal }} @@ -74,6 +76,11 @@ outputs: runs: using: 'composite' steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Set deployment mode id: mode shell: bash @@ -171,7 +178,7 @@ runs: echo "deploy-snap=${{ inputs.deploy-snap }}" >> $GITHUB_OUTPUT echo "deploy-microsoft=${{ inputs.deploy-microsoft }}" >> $GITHUB_OUTPUT echo "deploy-apple=${{ inputs.deploy-apple }}" >> $GITHUB_OUTPUT - echo "deploy-appimage=${{ inputs.deploy-appimage }}" >> $GITHUB_OUTPUT + echo "deploy-appimage=false" >> $GITHUB_OUTPUT # DISABLED: AppImage requires system WebKit2GTK echo "deploy-linux-terminal=${{ inputs.deploy-linux-terminal }}" >> $GITHUB_OUTPUT if [ "$MODE" = "production" ]; then diff --git a/.github/actions/deployment-summary/action.yml b/.github/actions/deployment-summary/action.yml index ba2b2628..d555c3dd 100644 --- a/.github/actions/deployment-summary/action.yml +++ b/.github/actions/deployment-summary/action.yml @@ -47,6 +47,11 @@ inputs: runs: using: 'composite' steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Generate summary shell: bash run: | diff --git a/.github/templates/RELEASE_TEMPLATE.md b/.github/templates/RELEASE_TEMPLATE.md index b8a7924d..00418e73 100644 --- a/.github/templates/RELEASE_TEMPLATE.md +++ b/.github/templates/RELEASE_TEMPLATE.md @@ -16,26 +16,6 @@ sudo snap install whodb ``` [View on Snapcraft](https://snapcraft.io/whodb) -### AppImage (Linux) - -Download the AppImage for your architecture from the assets below, make it executable, and run: - -```bash -# For AMD64/x86_64 -chmod +x WhoDB-{{VERSION}}-amd64.AppImage -./WhoDB-{{VERSION}}-amd64.AppImage - -# For ARM64/aarch64 -chmod +x WhoDB-{{VERSION}}-arm64.AppImage -./WhoDB-{{VERSION}}-arm64.AppImage -``` - -All AppImages are signed with Sigstore. To verify: - -```bash -cosign verify-blob --signature WhoDB-{{VERSION}}-amd64.AppImage.sig --certificate WhoDB-{{VERSION}}-amd64.AppImage.pem WhoDB-{{VERSION}}-amd64.AppImage -``` - ### Docker ```bash docker pull clidey/whodb:{{VERSION}} @@ -55,7 +35,6 @@ See assets below for platform-specific packages (DMG, MSIX, etc.). To upgrade from a previous version: - **Docker**: Pull the latest image and restart your container - **Snap**: Run `sudo snap refresh whodb` -- **AppImage**: Download the new AppImage and replace the old one - **Desktop Apps**: Download and install the new version --- diff --git a/.github/workflows/_build-appimage.yml b/.github/workflows/_build-appimage.yml index ce9f3ebb..4b6666a3 100644 --- a/.github/workflows/_build-appimage.yml +++ b/.github/workflows/_build-appimage.yml @@ -30,6 +30,11 @@ jobs: - runner: ubuntu-24.04-arm arch: arm64 steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/_build-apple.yml b/.github/workflows/_build-apple.yml index 03b5e0dd..4462ac3c 100644 --- a/.github/workflows/_build-apple.yml +++ b/.github/workflows/_build-apple.yml @@ -26,7 +26,7 @@ jobs: build-apple: name: Build macOS (${{ matrix.build-type }}) runs-on: macos-latest - environment: deploy-apple + environment: build-apple strategy: matrix: include: diff --git a/.github/workflows/_build-docker.yml b/.github/workflows/_build-docker.yml index 489709e4..3826526c 100644 --- a/.github/workflows/_build-docker.yml +++ b/.github/workflows/_build-docker.yml @@ -39,6 +39,11 @@ jobs: platform: linux/arm64 arch: arm64 steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/_build-linux-terminal.yml b/.github/workflows/_build-linux-terminal.yml index 01c2b4e3..df0e8f1f 100644 --- a/.github/workflows/_build-linux-terminal.yml +++ b/.github/workflows/_build-linux-terminal.yml @@ -18,6 +18,11 @@ jobs: runs-on: ubuntu-latest environment: permission-required steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/_build-snap.yml b/.github/workflows/_build-snap.yml index 5b974364..f294cab9 100644 --- a/.github/workflows/_build-snap.yml +++ b/.github/workflows/_build-snap.yml @@ -33,6 +33,11 @@ jobs: SNAPCRAFT_ENABLE_EXPERIMENTAL_EXTENSIONS: "1" SNAPCRAFT_PROJECT_VERSION: ${{ inputs.version }} steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/_deploy-docker.yml b/.github/workflows/_deploy-docker.yml index 77f1533a..9155b7ed 100644 --- a/.github/workflows/_deploy-docker.yml +++ b/.github/workflows/_deploy-docker.yml @@ -24,6 +24,11 @@ jobs: runs-on: ubuntu-latest environment: deploy-docker steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout for scripts uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/_deploy-homebrew.yml b/.github/workflows/_deploy-homebrew.yml index af431fb5..2f421d33 100644 --- a/.github/workflows/_deploy-homebrew.yml +++ b/.github/workflows/_deploy-homebrew.yml @@ -17,6 +17,11 @@ jobs: name: Generate Homebrew Cask runs-on: ubuntu-latest steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/_deploy-snap.yml b/.github/workflows/_deploy-snap.yml index ceae5fc9..0cf23e88 100644 --- a/.github/workflows/_deploy-snap.yml +++ b/.github/workflows/_deploy-snap.yml @@ -23,6 +23,11 @@ jobs: runs-on: ubuntu-latest environment: deploy-snap steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout for scripts uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/_sign-validate.yml b/.github/workflows/_sign-validate.yml index 15705e0a..30d365c7 100644 --- a/.github/workflows/_sign-validate.yml +++ b/.github/workflows/_sign-validate.yml @@ -17,11 +17,12 @@ on: required: false type: boolean default: true + # DISABLED: AppImage builds disabled - requires system WebKit2GTK validate-appimage: description: 'Whether to validate AppImage builds' required: false type: boolean - default: true + default: false jobs: sign-with-sigstore: @@ -31,6 +32,11 @@ jobs: contents: write id-token: write steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: @@ -50,18 +56,19 @@ jobs: pattern: desktop-* path: artifacts/ - - name: Download AppImages - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - continue-on-error: true - with: - pattern: appimage-* - path: artifacts/ + # DISABLED: AppImage builds disabled + # - name: Download AppImages + # uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + # continue-on-error: true + # with: + # pattern: appimage-* + # path: artifacts/ - - name: Restore executable permissions - run: | - echo "Restoring executable permissions for AppImages..." - find artifacts -name "*.AppImage" -type f -exec chmod +x {} \; - echo "✅ Permissions restored" + # - name: Restore executable permissions + # run: | + # echo "Restoring executable permissions for AppImages..." + # find artifacts -name "*.AppImage" -type f -exec chmod +x {} \; + # echo "✅ Permissions restored" - name: Install Cosign uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0 @@ -104,6 +111,11 @@ jobs: permissions: contents: read steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout for scripts uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: @@ -123,18 +135,19 @@ jobs: pattern: desktop-* path: artifacts/ - - name: Download AppImages - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - continue-on-error: true - with: - pattern: appimage-* - path: artifacts/ + # DISABLED: AppImage builds disabled + # - name: Download AppImages + # uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + # continue-on-error: true + # with: + # pattern: appimage-* + # path: artifacts/ - - name: Restore executable permissions - run: | - echo "Restoring executable permissions for AppImages..." - find artifacts -name "*.AppImage" -type f -exec chmod +x {} \; - echo "✅ Permissions restored" + # - name: Restore executable permissions + # run: | + # echo "Restoring executable permissions for AppImages..." + # find artifacts -name "*.AppImage" -type f -exec chmod +x {} \; + # echo "✅ Permissions restored" - name: Download signatures uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 @@ -218,8 +231,9 @@ jobs: exit 1 fi + # DISABLED: AppImage builds disabled - requires system WebKit2GTK - name: Validate AppImage artifacts - if: inputs.validate-appimage + if: inputs.validate-appimage # Will be false - AppImage disabled run: | echo "🐧 Validating AppImage artifacts..." FAILED=false @@ -280,7 +294,7 @@ jobs: "desktop": ${{ inputs.validate-desktop }}, "appimage": ${{ inputs.validate-appimage }} }, - "artifacts": $(find artifacts -type f -name "*.snap" -o -name "*.AppImage" -o -name "*.exe" -o -name "*.dmg" | wc -l) + "artifacts": $(find artifacts -type f -name "*.snap" -o -name "*.exe" -o -name "*.dmg" | wc -l) } EOF diff --git a/.github/workflows/_verify-deployment.yml b/.github/workflows/_verify-deployment.yml index d88a02be..9bf0c239 100644 --- a/.github/workflows/_verify-deployment.yml +++ b/.github/workflows/_verify-deployment.yml @@ -50,6 +50,11 @@ jobs: github-verified: ${{ steps.verify-github.outputs.verified }} all-verified: ${{ steps.summary.outputs.all-verified }} steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index cc937da1..65671cfa 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -20,6 +20,11 @@ jobs: pull-requests: write steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Post instruction comment uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: @@ -49,6 +54,11 @@ jobs: id-token: write steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout base branch (safe checkout) uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 3aff005b..495fd619 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -41,6 +41,11 @@ jobs: id-token: write actions: read # Required for Claude to read CI results on PRs steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout repository uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: diff --git a/.github/workflows/release-ce.yml b/.github/workflows/release-ce.yml index 97890b2e..acf6c618 100644 --- a/.github/workflows/release-ce.yml +++ b/.github/workflows/release-ce.yml @@ -57,11 +57,12 @@ on: required: false type: boolean default: false - deploy-appimage: - description: 'Build AppImage (for GitHub Release)' - required: false - type: boolean - default: false + # DISABLED: AppImage requires system WebKit2GTK - not truly portable + # deploy-appimage: + # description: 'Build AppImage (for GitHub Release)' + # required: false + # type: boolean + # default: false deploy-linux-terminal: description: 'Build Linux terminal binaries (amd64, arm64, riscv64, armv6, armv7)' required: false @@ -93,10 +94,15 @@ jobs: deploy-snap: ${{ steps.calc.outputs.deploy-snap }} deploy-microsoft: ${{ steps.calc.outputs.deploy-microsoft }} deploy-apple: ${{ steps.calc.outputs.deploy-apple }} - deploy-appimage: ${{ steps.calc.outputs.deploy-appimage }} + # deploy-appimage: ${{ steps.calc.outputs.deploy-appimage }} # DISABLED deploy-linux-terminal: ${{ steps.calc.outputs.deploy-linux-terminal }} publish-github-release: ${{ steps.calc.outputs.publish-github-release }} steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: @@ -127,7 +133,7 @@ jobs: deploy-snap: ${{ github.event_name == 'pull_request' && 'true' || (fromJSON(inputs.deploy-snap) && 'true' || 'false') }} deploy-microsoft: ${{ github.event_name == 'pull_request' && 'true' || (fromJSON(inputs.deploy-microsoft) && 'true' || 'false') }} deploy-apple: ${{ github.event_name == 'pull_request' && 'true' || (fromJSON(inputs.deploy-apple) && 'true' || 'false') }} - deploy-appimage: ${{ github.event_name == 'pull_request' && 'true' || (fromJSON(inputs.deploy-appimage) && 'true' || 'false') }} + deploy-appimage: 'false' # DISABLED: AppImage requires system WebKit2GTK deploy-linux-terminal: ${{ github.event_name == 'pull_request' && 'true' || (fromJSON(inputs.deploy-linux-terminal) && 'true' || 'false') }} publish-github-release: ${{ github.event_name == 'pull_request' && 'true' || (fromJSON(inputs.publish-github-release) && 'true' || 'false') }} @@ -152,7 +158,6 @@ jobs: echo "| Snap Store | ${{ steps.calc.outputs.deploy-snap }} | stable |" >> $GITHUB_STEP_SUMMARY echo "| Microsoft Store | ${{ steps.calc.outputs.deploy-microsoft }} | production |" >> $GITHUB_STEP_SUMMARY echo "| Apple App Store | ${{ steps.calc.outputs.deploy-apple }} | App Store |" >> $GITHUB_STEP_SUMMARY - echo "| AppImage | ${{ steps.calc.outputs.deploy-appimage }} | GitHub Release |" >> $GITHUB_STEP_SUMMARY else echo "| Store | Deploy | Channel |" >> $GITHUB_STEP_SUMMARY echo "|-------|--------|---------|" >> $GITHUB_STEP_SUMMARY @@ -160,7 +165,6 @@ jobs: echo "| Snap Store | ${{ steps.calc.outputs.deploy-snap }} | edge |" >> $GITHUB_STEP_SUMMARY echo "| Microsoft Store | ${{ steps.calc.outputs.deploy-microsoft }} | draft |" >> $GITHUB_STEP_SUMMARY echo "| Apple App Store | ${{ steps.calc.outputs.deploy-apple }} | TestFlight |" >> $GITHUB_STEP_SUMMARY - echo "| AppImage | ${{ steps.calc.outputs.deploy-appimage }} | GitHub Release |" >> $GITHUB_STEP_SUMMARY fi # Step 2: Build artifacts in parallel (only what's selected) @@ -204,15 +208,16 @@ jobs: version: ${{ needs.calculate-version.outputs.version }} secrets: inherit - build-appimage: - name: Build AppImage - needs: [ calculate-version ] - if: needs.calculate-version.outputs.deploy-appimage == 'true' - uses: ./.github/workflows/_build-appimage.yml - with: - version: ${{ needs.calculate-version.outputs.version }} - edition: 'ce' - secrets: inherit + # DISABLED: AppImage requires system WebKit2GTK - not truly portable + # build-appimage: + # name: Build AppImage + # needs: [ calculate-version ] + # if: needs.calculate-version.outputs.deploy-appimage == 'true' + # uses: ./.github/workflows/_build-appimage.yml + # with: + # version: ${{ needs.calculate-version.outputs.version }} + # edition: 'ce' + # secrets: inherit build-linux-terminal: name: Build Linux Terminal @@ -226,7 +231,7 @@ jobs: # Step 3: Sign and validate all builds (best effort - continues even if any build fails) sign-and-validate: name: Sign and Validate - needs: [ calculate-version, build-docker, build-windows, build-apple, build-snap, build-appimage, build-linux-terminal ] + needs: [ calculate-version, build-docker, build-windows, build-apple, build-snap, build-linux-terminal ] if: | always() && needs.calculate-version.result == 'success' && @@ -234,20 +239,19 @@ jobs: (needs.build-windows.result == 'success' || needs.build-windows.result == 'skipped' || needs.build-windows.result == 'failure') && (needs.build-apple.result == 'success' || needs.build-apple.result == 'skipped' || needs.build-apple.result == 'failure') && (needs.build-snap.result == 'success' || needs.build-snap.result == 'skipped' || needs.build-snap.result == 'failure') && - (needs.build-appimage.result == 'success' || needs.build-appimage.result == 'skipped' || needs.build-appimage.result == 'failure') && (needs.build-linux-terminal.result == 'success' || needs.build-linux-terminal.result == 'skipped' || needs.build-linux-terminal.result == 'failure') uses: ./.github/workflows/_sign-validate.yml with: version: ${{ needs.calculate-version.outputs.version }} validate-snap: ${{ needs.build-snap.result == 'success' }} validate-desktop: ${{ needs.build-windows.result == 'success' || needs.build-apple.result == 'success' }} - validate-appimage: ${{ needs.build-appimage.result == 'success' }} + validate-appimage: false # DISABLED: AppImage builds disabled # Step 4: Create GitHub release (only if ALL selected platforms built successfully) create-github-release: name: Create GitHub Release runs-on: ubuntu-latest - needs: [ calculate-version, build-docker, build-windows, build-apple, build-snap, build-appimage, build-linux-terminal ] + needs: [ calculate-version, build-docker, build-windows, build-apple, build-snap, build-linux-terminal ] if: | always() && needs.calculate-version.result == 'success' && @@ -255,11 +259,15 @@ jobs: (needs.calculate-version.outputs.deploy-snap != 'true' || needs.build-snap.result == 'success') && (needs.calculate-version.outputs.deploy-microsoft != 'true' || needs.build-windows.result == 'success') && (needs.calculate-version.outputs.deploy-apple != 'true' || needs.build-apple.result == 'success') && - (needs.calculate-version.outputs.deploy-appimage != 'true' || needs.build-appimage.result == 'success') && (needs.calculate-version.outputs.deploy-linux-terminal != 'true' || needs.build-linux-terminal.result == 'success') permissions: contents: write steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Checkout uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 with: @@ -279,12 +287,13 @@ jobs: pattern: desktop-* path: artifacts/ - - name: Download AppImages - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - continue-on-error: true - with: - pattern: appimage-* - path: artifacts/ + # DISABLED: AppImage builds disabled + # - name: Download AppImages + # uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + # continue-on-error: true + # with: + # pattern: appimage-* + # path: artifacts/ - name: Download Linux server binaries uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 @@ -304,9 +313,6 @@ jobs: run: | mkdir -p final-assets - # Copy AppImage packages - find artifacts -type f -name "*.AppImage" -exec cp {} final-assets/ \; 2>/dev/null || true - # Copy desktop builds (exe, dmg, msixbundle) find artifacts -type f \( -name "*.exe" -o -name "*.dmg" -o -name "*.msixbundle" \) -exec cp {} final-assets/ \; 2>/dev/null || true @@ -462,7 +468,6 @@ jobs: build-windows, build-apple, build-snap, - build-appimage, build-linux-terminal, sign-and-validate, deploy-docker, @@ -473,6 +478,11 @@ jobs: generate-homebrew-cask ] steps: + - name: Harden Runner + uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2 + with: + egress-policy: audit + - name: Generate comprehensive summary run: | echo "# 📊 Release Summary for ${{ needs.calculate-version.outputs.version }}" >> $GITHUB_STEP_SUMMARY @@ -518,14 +528,6 @@ jobs: echo "| Snap | ❌ Failed |" >> $GITHUB_STEP_SUMMARY fi - if [ "${{ needs.build-appimage.result }}" = "success" ]; then - echo "| AppImage | ✅ Success |" >> $GITHUB_STEP_SUMMARY - elif [ "${{ needs.build-appimage.result }}" = "skipped" ]; then - echo "| AppImage | ⏭️ Skipped |" >> $GITHUB_STEP_SUMMARY - else - echo "| AppImage | ❌ Failed |" >> $GITHUB_STEP_SUMMARY - fi - if [ "${{ needs.build-linux-terminal.result }}" = "success" ]; then echo "| Linux Terminal | ✅ Success |" >> $GITHUB_STEP_SUMMARY elif [ "${{ needs.build-linux-terminal.result }}" = "skipped" ]; then diff --git a/core/src/plugins/sqlite3/db.go b/core/src/plugins/sqlite3/db.go index 36f326e5..c53e99ef 100644 --- a/core/src/plugins/sqlite3/db.go +++ b/core/src/plugins/sqlite3/db.go @@ -48,6 +48,10 @@ func (p *Sqlite3Plugin) DB(config *engine.PluginConfig) (*gorm.DB, error) { } database := connectionInput.Database + if IsSampleDatabase(database) { + return GetSampleDatabase() + } + var fileNameDatabase string // Desktop mode: treat database field as full path diff --git a/core/src/plugins/sqlite3/sample.go b/core/src/plugins/sqlite3/sample.go new file mode 100644 index 00000000..0e99837d --- /dev/null +++ b/core/src/plugins/sqlite3/sample.go @@ -0,0 +1,83 @@ +/* + * Copyright 2025 Clidey, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sqlite3 + +import ( + _ "embed" + "sync" + + "github.com/clidey/whodb/core/src/engine" + "github.com/clidey/whodb/core/src/log" + "github.com/clidey/whodb/core/src/plugins" + "github.com/clidey/whodb/core/src/types" + "gorm.io/driver/sqlite" + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +//go:embed whodb-sample.sql +var sampleSQL string + +const SampleDatabaseName = "whodb-sample" + +const sampleDatabaseURI = "file:" + SampleDatabaseName + "?mode=memory&cache=shared" + +var ( + sampleDBOnce sync.Once + sampleDBErr error +) + +func IsSampleDatabase(name string) bool { + return name == SampleDatabaseName +} + +func GetSampleProfile() types.DatabaseCredentials { + return types.DatabaseCredentials{ + Alias: "Sample SQLite Database", + Database: SampleDatabaseName, + Type: engine.DatabaseType_Sqlite3, + IsProfile: true, + Source: "builtin", + } +} + +func GetSampleDatabase() (*gorm.DB, error) { + sampleDBOnce.Do(func() { + db, err := gorm.Open(sqlite.Open(sampleDatabaseURI), &gorm.Config{ + Logger: logger.Default.LogMode(plugins.GetGormLogConfig()), + }) + if err != nil { + log.Logger.WithError(err).Error("Failed to create sample in-memory database") + sampleDBErr = err + return + } + + if err := db.Exec(sampleSQL).Error; err != nil { + log.Logger.WithError(err).Error("Failed to initialize sample database schema") + sampleDBErr = err + return + } + }) + + if sampleDBErr != nil { + return nil, sampleDBErr + } + + return gorm.Open(sqlite.Open(sampleDatabaseURI), &gorm.Config{ + Logger: logger.Default.LogMode(plugins.GetGormLogConfig()), + }) +} diff --git a/core/src/plugins/sqlite3/sqlite3.go b/core/src/plugins/sqlite3/sqlite3.go index 84efa05c..9407055b 100644 --- a/core/src/plugins/sqlite3/sqlite3.go +++ b/core/src/plugins/sqlite3/sqlite3.go @@ -75,15 +75,16 @@ func (p *Sqlite3Plugin) FormTableName(schema string, storageUnit string) string } func (p *Sqlite3Plugin) GetDatabases(config *engine.PluginConfig) ([]string, error) { - // In desktop mode, return empty list - users will browse for files if env.GetIsDesktopMode() { return []string{}, nil } - // Server mode: scan default directory directory := getDefaultDirectory() entries, err := os.ReadDir(directory) if err != nil { + if os.IsNotExist(err) { + return []string{}, nil + } return nil, err } diff --git a/core/src/plugins/sqlite3/whodb-sample.sql b/core/src/plugins/sqlite3/whodb-sample.sql new file mode 100644 index 00000000..cd9159f1 --- /dev/null +++ b/core/src/plugins/sqlite3/whodb-sample.sql @@ -0,0 +1,317 @@ +-- Copyright 2025 Clidey, Inc. +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +-- WhoDB Sample Database +-- A simple e-commerce schema to demonstrate WhoDB features + +-- Enable foreign key support +PRAGMA +foreign_keys = ON; + +-- Users Table +CREATE TABLE IF NOT EXISTS users +( + id + INTEGER + PRIMARY + KEY + AUTOINCREMENT, + username + TEXT + UNIQUE + NOT + NULL, + email + TEXT + UNIQUE + NOT + NULL, + password + TEXT + NOT + NULL, + created_at + DATETIME + DEFAULT + CURRENT_TIMESTAMP, + CHECK ( + LENGTH +( + password +) >= 8) + ); + +-- Products Table +CREATE TABLE IF NOT EXISTS products +( + id + INTEGER + PRIMARY + KEY + AUTOINCREMENT, + name + TEXT + NOT + NULL + UNIQUE, + description + TEXT, + price + REAL + NOT + NULL + CHECK +( + price + >= + 0 +), + stock_quantity INTEGER NOT NULL DEFAULT 0 CHECK +( + stock_quantity + >= + 0 +), + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ); + +-- Orders Table +CREATE TABLE IF NOT EXISTS orders +( + id + INTEGER + PRIMARY + KEY + AUTOINCREMENT, + user_id + INTEGER + NOT + NULL, + order_date + DATETIME + DEFAULT + CURRENT_TIMESTAMP, + total_amount + REAL + NOT + NULL + DEFAULT + 0, + status + TEXT + DEFAULT + 'pending' + CHECK ( + status + IN +( + 'pending', + 'completed', + 'canceled' +)), + FOREIGN KEY +( + user_id +) REFERENCES users +( + id +) ON DELETE CASCADE + ); + +-- Order Items Table +CREATE TABLE IF NOT EXISTS order_items +( + id + INTEGER + PRIMARY + KEY + AUTOINCREMENT, + order_id + INTEGER + NOT + NULL, + product_id + INTEGER + NOT + NULL, + quantity + INTEGER + NOT + NULL + CHECK +( + quantity > + 0 +), + price_at_purchase REAL NOT NULL CHECK +( + price_at_purchase + >= + 0 +), + FOREIGN KEY +( + order_id +) REFERENCES orders +( + id +) ON DELETE CASCADE, + FOREIGN KEY +( + product_id +) REFERENCES products +( + id +) + ON DELETE CASCADE + ); + +-- Payments Table +CREATE TABLE IF NOT EXISTS payments +( + id + INTEGER + PRIMARY + KEY + AUTOINCREMENT, + order_id + INTEGER + NOT + NULL, + payment_date + DATETIME + DEFAULT + CURRENT_TIMESTAMP, + amount + REAL + NOT + NULL + CHECK +( + amount + >= + 0 +), + payment_method TEXT CHECK +( + payment_method + IN +( + 'credit_card', + 'paypal', + 'bank_transfer' +)), + FOREIGN KEY +( + order_id +) REFERENCES orders +( + id +) ON DELETE CASCADE + ); + +-- Indexes for faster queries +CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); +CREATE INDEX IF NOT EXISTS idx_orders_user_id ON orders(user_id); +CREATE INDEX IF NOT EXISTS idx_order_items_order_id ON order_items(order_id); +CREATE INDEX IF NOT EXISTS idx_payments_order_id ON payments(order_id); + +-- View for Order Summary +CREATE VIEW IF NOT EXISTS order_summary AS +SELECT o.id AS order_id, + u.username, + o.order_date, + o.status, + o.total_amount +FROM orders o + JOIN users u ON o.user_id = u.id; + +-- Triggers to update total_amount in orders +CREATE TRIGGER IF NOT EXISTS trg_insert_order_total +AFTER INSERT ON order_items +BEGIN +UPDATE orders +SET total_amount = (SELECT COALESCE(SUM(price_at_purchase * quantity), 0) + FROM order_items + WHERE order_id = NEW.order_id) +WHERE id = NEW.order_id; +END; + +CREATE TRIGGER IF NOT EXISTS trg_update_order_total +AFTER +UPDATE ON order_items +BEGIN +UPDATE orders +SET total_amount = (SELECT COALESCE(SUM(price_at_purchase * quantity), 0) + FROM order_items + WHERE order_id = NEW.order_id) +WHERE id = NEW.order_id; +END; + +CREATE TRIGGER IF NOT EXISTS trg_delete_order_total +AFTER +DELETE +ON order_items +BEGIN +UPDATE orders +SET total_amount = (SELECT COALESCE(SUM(price_at_purchase * quantity), 0) + FROM order_items + WHERE order_id = OLD.order_id) +WHERE id = OLD.order_id; +END; + +-- Sample Data for Users +INSERT INTO users (username, email, password) +VALUES ('john_doe', 'john@example.com', 'securepassword1'), + ('jane_smith', 'jane@example.com', 'securepassword2'), + ('admin_user', 'admin@example.com', 'adminpass1'); + +-- Sample Data for Products +INSERT INTO products (name, description, price, stock_quantity) +VALUES ('Laptop', 'High-performance laptop', 1200.00, 10), + ('Smartphone', 'Latest model smartphone', 800.00, 20), + ('Headphones', 'Noise-canceling headphones', 150.00, 50), + ('Monitor', '4K UHD Monitor', 400.00, 15); + +-- Sample Orders +INSERT INTO orders (user_id, total_amount, status) +VALUES (1, 0, 'completed'), + (2, 0, 'pending'); + +-- Sample Order Items (triggers will update total_amount) +INSERT INTO order_items (order_id, product_id, quantity, price_at_purchase) +VALUES (1, 1, 1, 1200.00), + (1, 2, 1, 800.00), + (2, 3, 1, 150.00); + +/* + * Copyright 2025 Clidey, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +-- Sample Payments +INSERT INTO payments (order_id, amount, payment_method) +VALUES (1, 2000.00, 'credit_card'), + (2, 150.00, 'paypal'); diff --git a/core/src/src.go b/core/src/src.go index 6e409127..e8ad9a48 100644 --- a/core/src/src.go +++ b/core/src/src.go @@ -59,6 +59,8 @@ func InitializeEngine() *engine.Engine { MainEngine.RegistryPlugin(elasticsearch.NewElasticSearchPlugin()) MainEngine.RegistryPlugin(clickhouse.NewClickHousePlugin()) + MainEngine.AddLoginProfile(sqlite3.GetSampleProfile()) + // Initialize Enterprise Edition plugins if available if initEE != nil { initEE(MainEngine) diff --git a/ee b/ee index 90256871..092ade24 160000 --- a/ee +++ b/ee @@ -1 +1 @@ -Subproject commit 9025687197314f16fa4a674cafb0f1467eaf3bf5 +Subproject commit 092ade2449fc983b330ca6a1c4d07561b36a8aae diff --git a/frontend/package.json b/frontend/package.json index 56246c95..d5d301f2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -108,5 +108,5 @@ "vite": "7.1.11", "vite-plugin-istanbul": "7.2.1" }, - "packageManager": "pnpm@10.20.0+sha512.cf9998222162dd85864d0a8102e7892e7ba4ceadebbf5a31f9c2fce48dfce317a9c53b9f6464d1ef9042cba2e02ae02a9f7c143a2b438cd93c91840f0192b9dd" + "packageManager": "pnpm@10.24.0+sha512.01ff8ae71b4419903b65c60fb2dc9d34cf8bb6e06d03bde112ef38f7a34d6904c424ba66bea5cdcf12890230bf39f9580473140ed9c946fef328b6e5238a345a" }