diff --git a/.github/workflows/build-app-beta.yaml b/.github/workflows/build-app-beta.yaml index ca9df362f..e5948beb2 100644 --- a/.github/workflows/build-app-beta.yaml +++ b/.github/workflows/build-app-beta.yaml @@ -6,9 +6,13 @@ name: Electron app BETA push: tags: - v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+ +permissions: + id-token: write + contents: write jobs: build: runs-on: ${{ matrix.os }} + environment: dbgate-app strategy: fail-fast: false matrix: @@ -60,21 +64,53 @@ jobs: - name: Install Snapcraft if: matrix.os == 'ubuntu-22.04' uses: samuelmeuli/action-snapcraft@v1 - - name: Publish + - name: Publish Windows + if: matrix.os == 'windows-2022' + run: | + + yarn run build:app + - name: Publish MacOS + if: matrix.os == 'macos-14' run: | yarn run build:app env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }} - WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }} CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }} CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}} + - name: Publish Linux + if: matrix.os == 'ubuntu-22.04' + run: | + + yarn run build:app + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} + - name: Azure login (OIDC) + uses: azure/login@v2 + if: matrix.os == 'windows-2022' + with: + client-id: ${{ secrets.AZURE_TC_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }} + allow-no-subscriptions: true + - name: Sign Windows artifacts with Azure Trusted Signing + uses: azure/trusted-signing-action@v0 + if: matrix.os == 'windows-2022' + with: + endpoint: https://wus3.codesigning.azure.net/ + trusted-signing-account-name: DbGate + certificate-profile-name: DbGate-Release + files-folder: app/dist + files-folder-filter: exe + timestamp-rfc3161: http://timestamp.acs.microsoft.com + timestamp-digest: SHA256 + - name: Fix YML hashes + if: matrix.os == 'windows-2022' + run: | + + yarn run fixYmlHashes - name: Copy artifacts run: | mkdir artifacts diff --git a/.github/workflows/build-app-check.yaml b/.github/workflows/build-app-check.yaml index c5686419e..173a21fad 100644 --- a/.github/workflows/build-app-check.yaml +++ b/.github/workflows/build-app-check.yaml @@ -6,9 +6,13 @@ name: Electron app check build push: tags: - check-[0-9]+-[0-9]+-[0-9]+.[0-9]+ +permissions: + id-token: write + contents: write jobs: build: runs-on: ${{ matrix.os }} + environment: dbgate-app strategy: fail-fast: false matrix: @@ -56,21 +60,53 @@ jobs: - name: Install Snapcraft if: matrix.os == 'ubuntu-22.04' uses: samuelmeuli/action-snapcraft@v1 - - name: Publish + - name: Publish Windows + if: matrix.os == 'windows-2022' + run: | + + yarn run build:app + - name: Publish MacOS + if: matrix.os == 'macos-14' run: | yarn run build:app env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }} - WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }} CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }} CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}} + - name: Publish Linux + if: matrix.os == 'ubuntu-22.04' + run: | + + yarn run build:app + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} + - name: Azure login (OIDC) + uses: azure/login@v2 + if: matrix.os == 'windows-2022' + with: + client-id: ${{ secrets.AZURE_TC_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }} + allow-no-subscriptions: true + - name: Sign Windows artifacts with Azure Trusted Signing + uses: azure/trusted-signing-action@v0 + if: matrix.os == 'windows-2022' + with: + endpoint: https://wus3.codesigning.azure.net/ + trusted-signing-account-name: DbGate + certificate-profile-name: DbGate-Release + files-folder: app/dist + files-folder-filter: exe + timestamp-rfc3161: http://timestamp.acs.microsoft.com + timestamp-digest: SHA256 + - name: Fix YML hashes + if: matrix.os == 'windows-2022' + run: | + + yarn run fixYmlHashes - name: Copy artifacts run: | mkdir artifacts diff --git a/.github/workflows/build-app-pro-beta.yaml b/.github/workflows/build-app-pro-beta.yaml index 4f1cd8591..ab87a8b0d 100644 --- a/.github/workflows/build-app-pro-beta.yaml +++ b/.github/workflows/build-app-pro-beta.yaml @@ -6,9 +6,13 @@ name: Electron app PREMIUM BETA push: tags: - v[0-9]+.[0-9]+.[0-9]+-premium-beta.[0-9]+ +permissions: + id-token: write + contents: write jobs: build: runs-on: ${{ matrix.os }} + environment: dbgate-app strategy: fail-fast: false matrix: @@ -39,7 +43,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 11203754aad94189b565c2816d37760b15c8e07f + ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro @@ -87,23 +91,61 @@ jobs: cd dbgate-merged yarn fillPackagedPlugins - - name: Publish + - name: Publish Windows + if: matrix.os == 'windows-2022' + run: | + cd .. + cd dbgate-merged + + yarn run build:app + - name: Publish MacOS + if: matrix.os == 'macos-14' run: | cd .. cd dbgate-merged yarn run build:app env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }} - WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }} CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }} CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}} + - name: Publish Linux + if: matrix.os == 'ubuntu-22.04' + run: | + cd .. + cd dbgate-merged + + yarn run build:app + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} + - name: Azure login (OIDC) + uses: azure/login@v2 + if: matrix.os == 'windows-2022' + with: + client-id: ${{ secrets.AZURE_TC_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }} + allow-no-subscriptions: true + - name: Sign Windows artifacts with Azure Trusted Signing + uses: azure/trusted-signing-action@v0 + if: matrix.os == 'windows-2022' + with: + endpoint: https://wus3.codesigning.azure.net/ + trusted-signing-account-name: DbGate + certificate-profile-name: DbGate-Release + files-folder: ../dbgate-merged/app/dist + files-folder-filter: exe + timestamp-rfc3161: http://timestamp.acs.microsoft.com + timestamp-digest: SHA256 + - name: Fix YML hashes + if: matrix.os == 'windows-2022' + run: | + cd .. + cd dbgate-merged + + yarn run fixYmlHashes - name: Copy artifacts run: | mkdir artifacts diff --git a/.github/workflows/build-app-pro.yaml b/.github/workflows/build-app-pro.yaml index 6ad30d299..9e5f06d81 100644 --- a/.github/workflows/build-app-pro.yaml +++ b/.github/workflows/build-app-pro.yaml @@ -6,9 +6,13 @@ name: Electron app PREMIUM push: tags: - v[0-9]+.[0-9]+.[0-9]+ +permissions: + id-token: write + contents: write jobs: build: runs-on: ${{ matrix.os }} + environment: dbgate-app strategy: fail-fast: false matrix: @@ -39,7 +43,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 11203754aad94189b565c2816d37760b15c8e07f + ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro @@ -87,23 +91,61 @@ jobs: cd dbgate-merged yarn fillPackagedPlugins - - name: Publish + - name: Publish Windows + if: matrix.os == 'windows-2022' + run: | + cd .. + cd dbgate-merged + + yarn run build:app + - name: Publish MacOS + if: matrix.os == 'macos-14' run: | cd .. cd dbgate-merged yarn run build:app env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }} - WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }} CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }} CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}} + - name: Publish Linux + if: matrix.os == 'ubuntu-22.04' + run: | + cd .. + cd dbgate-merged + + yarn run build:app + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} + - name: Azure login (OIDC) + uses: azure/login@v2 + if: matrix.os == 'windows-2022' + with: + client-id: ${{ secrets.AZURE_TC_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }} + allow-no-subscriptions: true + - name: Sign Windows artifacts with Azure Trusted Signing + uses: azure/trusted-signing-action@v0 + if: matrix.os == 'windows-2022' + with: + endpoint: https://wus3.codesigning.azure.net/ + trusted-signing-account-name: DbGate + certificate-profile-name: DbGate-Release + files-folder: ../dbgate-merged/app/dist + files-folder-filter: exe + timestamp-rfc3161: http://timestamp.acs.microsoft.com + timestamp-digest: SHA256 + - name: Fix YML hashes + if: matrix.os == 'windows-2022' + run: | + cd .. + cd dbgate-merged + + yarn run fixYmlHashes - name: Copy artifacts run: | mkdir artifacts diff --git a/.github/workflows/build-app.yaml b/.github/workflows/build-app.yaml index 22545dd62..212f72a2b 100644 --- a/.github/workflows/build-app.yaml +++ b/.github/workflows/build-app.yaml @@ -6,9 +6,13 @@ name: Electron app push: tags: - v[0-9]+.[0-9]+.[0-9]+ +permissions: + id-token: write + contents: write jobs: build: runs-on: ${{ matrix.os }} + environment: dbgate-app strategy: fail-fast: false matrix: @@ -56,24 +60,56 @@ jobs: - name: Install Snapcraft if: matrix.os == 'ubuntu-22.04' uses: samuelmeuli/action-snapcraft@v1 - - name: Publish + - name: Publish Windows + if: matrix.os == 'windows-2022' + run: | + + yarn run build:app + - name: Publish MacOS + if: matrix.os == 'macos-14' run: | yarn run build:app env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }} - WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }} CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }} CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}} + - name: Publish Linux + if: matrix.os == 'ubuntu-22.04' + run: | + + yarn run build:app + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} - name: generatePadFile run: | yarn generatePadFile + - name: Azure login (OIDC) + uses: azure/login@v2 + if: matrix.os == 'windows-2022' + with: + client-id: ${{ secrets.AZURE_TC_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }} + allow-no-subscriptions: true + - name: Sign Windows artifacts with Azure Trusted Signing + uses: azure/trusted-signing-action@v0 + if: matrix.os == 'windows-2022' + with: + endpoint: https://wus3.codesigning.azure.net/ + trusted-signing-account-name: DbGate + certificate-profile-name: DbGate-Release + files-folder: app/dist + files-folder-filter: exe + timestamp-rfc3161: http://timestamp.acs.microsoft.com + timestamp-digest: SHA256 + - name: Fix YML hashes + if: matrix.os == 'windows-2022' + run: | + + yarn run fixYmlHashes - name: Copy artifacts run: | mkdir artifacts diff --git a/.github/workflows/build-cloud-pro.yaml b/.github/workflows/build-cloud-pro.yaml index dc5cb248e..d5bdce153 100644 --- a/.github/workflows/build-cloud-pro.yaml +++ b/.github/workflows/build-cloud-pro.yaml @@ -39,7 +39,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 11203754aad94189b565c2816d37760b15c8e07f + ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-docker-pro.yaml b/.github/workflows/build-docker-pro.yaml index 519e08fe7..1fd89b418 100644 --- a/.github/workflows/build-docker-pro.yaml +++ b/.github/workflows/build-docker-pro.yaml @@ -44,7 +44,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 11203754aad94189b565c2816d37760b15c8e07f + ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-npm-pro.yaml b/.github/workflows/build-npm-pro.yaml index 054be0c9c..14d6d6991 100644 --- a/.github/workflows/build-npm-pro.yaml +++ b/.github/workflows/build-npm-pro.yaml @@ -7,6 +7,9 @@ name: NPM packages PREMIUM tags: - v[0-9]+.[0-9]+.[0-9]+ - v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+ +permissions: + id-token: write + contents: write jobs: build: runs-on: ${{ matrix.os }} @@ -32,7 +35,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 11203754aad94189b565c2816d37760b15c8e07f + ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro @@ -49,13 +52,8 @@ jobs: cd .. cd dbgate-merged node adjustNpmPackageJsonPremium - - name: Configure NPM token - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - cd .. - cd dbgate-merged - npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" + - name: Update npm + run: npm install -g npm@latest - name: Remove dbmodel - should be not published run: | cd .. @@ -71,28 +69,35 @@ jobs: cd .. cd dbgate-merged yarn setCurrentVersion + - name: Compute npm dist-tag + run: | + if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then + echo "NPM_TAG=alpha" >> $GITHUB_ENV + else + echo "NPM_TAG=latest" >> $GITHUB_ENV + fi - name: Publish dbgate-api-premium run: | cd .. cd dbgate-merged/packages/api - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-web-premium run: | cd .. cd dbgate-merged/packages/web - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-serve-premium run: | cd .. cd dbgate-merged/packages/serve - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-cosmosdb run: | cd .. cd dbgate-merged/plugins/dbgate-plugin-cosmosdb - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-firestore run: | cd .. cd dbgate-merged/plugins/dbgate-plugin-firestore - npm publish + npm publish --tag "$NPM_TAG" diff --git a/.github/workflows/build-npm.yaml b/.github/workflows/build-npm.yaml index 9b815cea7..079c25f8a 100644 --- a/.github/workflows/build-npm.yaml +++ b/.github/workflows/build-npm.yaml @@ -7,6 +7,9 @@ name: NPM packages tags: - v[0-9]+.[0-9]+.[0-9]+ - v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+ +permissions: + id-token: write + contents: write jobs: build: runs-on: ${{ matrix.os }} @@ -26,103 +29,107 @@ jobs: uses: actions/setup-node@v1 with: node-version: 22.x - - name: Configure NPM token - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" + - name: Update npm + run: npm install -g npm@latest - name: yarn install run: | yarn install - name: setCurrentVersion run: | yarn setCurrentVersion + - name: Compute npm dist-tag + run: | + if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then + echo "NPM_TAG=alpha" >> $GITHUB_ENV + else + echo "NPM_TAG=latest" >> $GITHUB_ENV + fi - name: Publish types working-directory: packages/types run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish tools working-directory: packages/tools run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish sqltree working-directory: packages/sqltree run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish api working-directory: packages/api run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish datalib working-directory: packages/datalib run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish filterparser working-directory: packages/filterparser run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish web working-directory: packages/web run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-serve working-directory: packages/serve run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbmodel working-directory: packages/dbmodel run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-csv working-directory: plugins/dbgate-plugin-csv run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-xml working-directory: plugins/dbgate-plugin-xml run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-excel working-directory: plugins/dbgate-plugin-excel run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-mssql working-directory: plugins/dbgate-plugin-mssql run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-mysql working-directory: plugins/dbgate-plugin-mysql run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-mongo working-directory: plugins/dbgate-plugin-mongo run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-postgres working-directory: plugins/dbgate-plugin-postgres run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-sqlite working-directory: plugins/dbgate-plugin-sqlite run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-redis working-directory: plugins/dbgate-plugin-redis run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-oracle working-directory: plugins/dbgate-plugin-oracle run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-clickhouse working-directory: plugins/dbgate-plugin-clickhouse run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-dbf working-directory: plugins/dbgate-plugin-dbf run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-cassandra working-directory: plugins/dbgate-plugin-cassandra run: | - npm publish + npm publish --tag "$NPM_TAG" diff --git a/.github/workflows/e2e-pro.yaml b/.github/workflows/e2e-pro.yaml index 7df23b243..0849eede4 100644 --- a/.github/workflows/e2e-pro.yaml +++ b/.github/workflows/e2e-pro.yaml @@ -26,7 +26,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 11203754aad94189b565c2816d37760b15c8e07f + ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/CHANGELOG.md b/CHANGELOG.md index 82ddc86c2..d9eadcdeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,24 @@ Builds: - linux - application for linux - win - application for Windows +## 6.6.8 +- CHANGED: Windows executable now uses Azure trusted signing certificate +- CHANGED: NPM packages now use GitHub OIDC provenance signing for better security +- CHANGED: Some features moved to Premium edition (master/detail views, FK lookups, column expansion, split view, advanced export/import, data archives, grouping, macros) + +## 6.6.6 +- ADDED: Allow disable/re-enable filter #1174 +- ADDED: Close right side tabs #1219 +- ADDED: Ability disable execute current line in query editor #1209 +- ADDED: Support for Redis Cluster #1204 (Premium) + ## 6.6.5 - ADDED: SQL AI assistant - powered by database chat, could help you to write SQL queries (Premium) - ADDED: Explain SQL error (powered by AI) (Premium) - ADDED: Database chat (and SQL AI Assistant) now supports showing charts (Premium) - FIXED: Fxied editing new files and roles (Team Premium) - FIXED: Connection to standalone database could be now pinned +- FIXED: Cannot open up large JSON file #1215 ## 6.6.4 - ADDED: AI Database chat now supports much more LLM models. (Premium) diff --git a/README.md b/README.md index 40b0051af..639af9c4c 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,9 @@ DbGate is licensed under GPL-3.0 license and is free to use for any purpose. * Try it online - [demo.dbgate.org](https://demo.dbgate.org) - online demo application * **Download** application for Windows, Linux or Mac from [dbgate.io](https://www.dbgate.io/download/) -* Looking for DbGate Community? **Download** from [dbgate.org](https://dbgate.org/download/) +* Looking for DbGate Community? **Download** from [dbgate.io](https://www.dbgate.io/download-community/) * Run web version as [NPM package](https://www.npmjs.com/package/dbgate-serve) or as [docker image](https://hub.docker.com/r/dbgate/dbgate) * Use nodeJs [scripting interface](https://docs.dbgate.io/scripting) ([API documentation](https://docs.dbgate.io/apidoc)) -* [Recommend DbGate](https://testimonial.to/dbgate) | [Rate on G2](https://www.g2.com/products/dbgate/reviews) -* [Give us feedback](https://dbgate.org/feedback) - it will help us to decide, how to improve DbGate in future -* We [offer 2-year PREMIUM license](https://dbgate.org/review/) for any honest review on these platforms (time-limited offer) ## Supported databases * MySQL @@ -93,7 +90,6 @@ Any contributions are welcome. If you want to contribute without coding, conside * Tell your friends about DbGate or share on social networks - when more people will use DbGate, it will grow to be better * Purchase a [DbGate Premium](https://www.dbgate.io/purchase/premium/) license -* Write review on [Product Hunt](https://www.producthunt.com/products/dbgate) or [G2](https://www.g2.com/products/dbgate/reviews) - we offer [2-year PREMIUM license](https://dbgate.org/review/) for reviewers (time limited offer) * Create issue, if you find problem in app, or you have idea to new feature. If issue already exists, you could leave comment on it, to prioritise most wanted issues * Create some tutorial video on [youtube](https://www.youtube.com/playlist?list=PLCo7KjCVXhr0RfUSjM9wJMsp_ShL1q61A) * Become a backer on [GitHub sponsors](https://github.com/sponsors/dbgate) or [Open collective](https://opencollective.com/dbgate) diff --git a/app/package.json b/app/package.json index 8db96276c..32fa1276e 100644 --- a/app/package.json +++ b/app/package.json @@ -117,7 +117,7 @@ "scripts": { "start": "cross-env ELECTRON_START_URL=http://localhost:5001 DEVMODE=1 electron .", "start:local": "cross-env electron .", - "dist": "electron-builder", + "dist": "electron-builder --publish never", "build": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn dist", "build:local": "cd ../packages/api && yarn build && cd ../web && yarn build && cd ../../app && yarn predist", "postinstall": "yarn rebuild && patch-package", diff --git a/common/fixYmlHashes.js b/common/fixYmlHashes.js new file mode 100644 index 000000000..bf317ef23 --- /dev/null +++ b/common/fixYmlHashes.js @@ -0,0 +1,110 @@ +import fs from 'node:fs/promises'; +import { createHash } from 'node:crypto'; +import path from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; +import YAML from 'yaml'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +async function sha512Base64(filePath) { + const buf = await fs.readFile(filePath); + const h = createHash('sha512'); + h.update(buf); + return h.digest('base64'); +} + +async function fileSize(filePath) { + const st = await fs.stat(filePath); + return st.size; +} + +async function fixOneYaml(ymlPath, distDir) { + let raw; + try { + raw = await fs.readFile(ymlPath, 'utf8'); + } catch (e) { + console.error(`✗ Cannot read ${ymlPath}:`, e.message); + return; + } + + let doc; + try { + doc = YAML.parse(raw); + } catch (e) { + console.error(`✗ Cannot parse YAML ${ymlPath}:`, e.message); + return; + } + + if (!doc || !Array.isArray(doc.files)) { + console.warn(`! ${path.basename(ymlPath)} has no 'files' array — skipped.`); + return; + } + + let changed = false; + + // Update each files[i].sha512 and files[i].size based on files[i].url + for (const entry of doc.files) { + if (!entry?.url) continue; + + const target = path.resolve(distDir, entry.url); + try { + const [hash, size] = await Promise.all([sha512Base64(target), fileSize(target)]); + if (entry.sha512 !== hash || entry.size !== size) { + console.log(`• ${path.basename(ymlPath)}: refresh ${entry.url}`); + entry.sha512 = hash; + entry.size = size; + changed = true; + } + } catch (e) { + console.warn( + `! Missing or unreadable file for ${entry.url} (referenced by ${path.basename(ymlPath)}): ${e.message}` + ); + } + } + + // Update top-level sha512 for the primary "path" file if present + if (doc.path) { + const primary = path.resolve(distDir, doc.path); + try { + const hash = await sha512Base64(primary); + if (doc.sha512 !== hash) { + console.log(`• ${path.basename(ymlPath)}: refresh top-level sha512 for path=${doc.path}`); + doc.sha512 = hash; + changed = true; + } + } catch (e) { + console.warn(`! Primary 'path' file not found for ${path.basename(ymlPath)}: ${doc.path} (${e.message})`); + } + } + + if (changed) { + const out = YAML.stringify(doc); + await fs.writeFile(ymlPath, out, 'utf8'); + console.log(`✓ Updated ${path.basename(ymlPath)}`); + } else { + console.log(`= No changes for ${path.basename(ymlPath)}`); + } +} + +async function main() { + const distDir = path.resolve(process.argv[2] ?? path.join(__dirname, '..', 'app', 'dist')); + const entries = await fs.readdir(distDir); + const ymls = entries.filter(f => f.toLowerCase().endsWith('.yml')); + + if (ymls.length === 0) { + console.warn(`No .yml files found in ${distDir}`); + return; + } + + console.log(`Scanning ${distDir}`); + for (const y of ymls) { + await fixOneYaml(path.join(distDir, y), distDir); + } +} + +main().catch(err => { + console.error(err); + process.exit(1); +}); diff --git a/e2e-tests/cypress/e2e/charts.cy.js b/e2e-tests/cypress/e2e/charts.cy.js index b1196aa2a..0bd54c4b0 100644 --- a/e2e-tests/cypress/e2e/charts.cy.js +++ b/e2e-tests/cypress/e2e/charts.cy.js @@ -110,7 +110,7 @@ describe('Charts', () => { cy.themeshot('new-object-window'); }); - it('Database chat - charts', () => { + it.only('Database chat - charts', () => { cy.contains('MySql-connection').click(); cy.contains('MyChinook').click(); cy.testid('TabsPanel_buttonNewObject').click(); @@ -119,8 +119,7 @@ describe('Charts', () => { cy.get('body').realType('show me chart of most popular genres'); cy.get('body').realPress('{enter}'); cy.testid('DatabaseChatTab_executeAllQueries', { timeout: 30000 }).click(); - cy.wait(5000); - cy.testid('chart-canvas').should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/)); + cy.testid('chart-canvas', { timeout: 30000 }).should($c => expect($c[0].toDataURL()).to.match(/^data:image\/png;base64/)); cy.themeshot('database-chat-chart'); }); diff --git a/package.json b/package.json index 3527d74f4..c5a96e6a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "6.6.6-premium-beta.2", + "version": "6.6.9", "name": "dbgate-all", "workspaces": [ "packages/*", @@ -52,6 +52,7 @@ "generatePadFile": "node generatePadFile", "fillPackagedPlugins": "node fillPackagedPlugins", "resetPackagedPlugins": "node resetPackagedPlugins", + "fixYmlHashes": "cd common && yarn init -y && yarn add yaml -W && cd .. && node common/fixYmlHashes.js app/dist", "prettier": "prettier --write packages/api/src && prettier --write packages/datalib/src && prettier --write packages/filterparser/src && prettier --write packages/sqltree/src && prettier --write packages/tools/src && prettier --write packages/types && prettier --write packages/web/src && prettier --write app/src", "copy:docker:build": "copyfiles packages/api/dist/* docker -f && copyfiles packages/web/public/* docker -u 2 && copyfiles \"packages/web/public/**/*\" docker -u 2 && copyfiles \"plugins/dist/**/*\" docker/plugins -u 2", "copy:packer:build": "copyfiles packages/api/dist/* packer/build -f && copyfiles packages/web/public/* packer/build -u 2 && copyfiles \"packages/web/public/**/*\" packer/build -u 2 && copyfiles \"plugins/dist/**/*\" packer/build/plugins -u 2 && copyfiles packer/install-packages.sh packer/build -f && yarn install:drivers:packer", diff --git a/packages/api/src/controllers/cloud.js b/packages/api/src/controllers/cloud.js index 4eb72caee..ad348b1f7 100644 --- a/packages/api/src/controllers/cloud.js +++ b/packages/api/src/controllers/cloud.js @@ -9,6 +9,8 @@ const { putCloudContent, removeCloudCachedConnection, getPromoWidgetData, + getPromoWidgetList, + getPromoWidgetPreview, } = require('../utility/cloudIntf'); const connections = require('./connections'); const socket = require('../utility/socket'); @@ -286,7 +288,7 @@ module.exports = { premiumPromoWidget_meta: true, async premiumPromoWidget() { - const data = getPromoWidgetData(); + const data = await getPromoWidgetData(); if (data?.state != 'data') { return null; } @@ -296,6 +298,16 @@ module.exports = { return data; }, + promoWidgetList_meta: true, + async promoWidgetList() { + return getPromoWidgetList(); + }, + + promoWidgetPreview_meta: true, + async promoWidgetPreview({ campaign, variant }) { + return getPromoWidgetPreview(campaign, variant); + }, + // chatStream_meta: { // raw: true, // method: 'post', diff --git a/packages/api/src/controllers/runners.js b/packages/api/src/controllers/runners.js index 3ff917e6e..d11482f47 100644 --- a/packages/api/src/controllers/runners.js +++ b/packages/api/src/controllers/runners.js @@ -274,8 +274,6 @@ module.exports = { start_meta: true, async start({ script }, req) { - await testStandardPermission('run-shell-script', req); - const runid = crypto.randomUUID(); if (script.type == 'json') { @@ -291,6 +289,8 @@ module.exports = { return this.startCore(runid, scriptTemplate(js, false)); } + await testStandardPermission('run-shell-script', req); + if (!platformInfo.allowShellScripting) { sendToAuditLog(req, { category: 'shell', diff --git a/packages/api/src/controllers/serverConnections.js b/packages/api/src/controllers/serverConnections.js index e182f2184..d561f3865 100644 --- a/packages/api/src/controllers/serverConnections.js +++ b/packages/api/src/controllers/serverConnections.js @@ -209,11 +209,11 @@ module.exports = { return Promise.resolve(); } this.lastPinged[conid] = new Date().getTime(); - const opened = await this.ensureOpened(conid); - if (!opened) { - return Promise.resolve(); - } try { + const opened = await this.ensureOpened(conid); + if (!opened) { + return Promise.resolve(); + } opened.subprocess.send({ msgtype: 'ping' }); } catch (err) { logger.error(extractErrorLogData(err), 'DBGM-00121 Error pinging server connection'); diff --git a/packages/api/src/controllers/sessions.js b/packages/api/src/controllers/sessions.js index 14c8a7bed..f05034bb9 100644 --- a/packages/api/src/controllers/sessions.js +++ b/packages/api/src/controllers/sessions.js @@ -97,6 +97,12 @@ module.exports = { socket.emit(`session-initialize-file-${jslid}`); }, + handle_changedCurrentDatabase(sesid, props) { + const { database } = props; + this.dispatchMessage(sesid, `Current database changed to ${database}`); + socket.emit(`session-changedb-${sesid}`, { database }); + }, + handle_ping() {}, create_meta: true, diff --git a/packages/api/src/utility/cloudIntf.js b/packages/api/src/utility/cloudIntf.js index 9b3286768..b0ea4217a 100644 --- a/packages/api/src/utility/cloudIntf.js +++ b/packages/api/src/utility/cloudIntf.js @@ -18,6 +18,7 @@ const logger = getLogger('cloudIntf'); let cloudFiles = null; let promoWidgetData = null; +let promoWidgetDataLoaded = false; const DBGATE_IDENTITY_URL = process.env.LOCAL_DBGATE_IDENTITY ? 'http://localhost:3103' @@ -260,13 +261,21 @@ async function getPublicFileData(path) { return resp.data; } -async function updatePremiumPromoWidget() { +async function ensurePromoWidgetDataLoaded() { + if (promoWidgetDataLoaded) { + return; + } try { const fileContent = await fs.readFile(path.join(datadir(), 'promo-widget.json'), 'utf-8'); promoWidgetData = JSON.parse(fileContent); } catch (err) { promoWidgetData = null; } + promoWidgetDataLoaded = true; +} + +async function updatePremiumPromoWidget() { + await ensurePromoWidgetDataLoaded(); const tags = (await collectCloudFilesSearchTags()).join(','); @@ -466,10 +475,21 @@ async function getPublicIpInfo() { } } -function getPromoWidgetData() { +async function getPromoWidgetData() { + await ensurePromoWidgetDataLoaded(); return promoWidgetData; } +async function getPromoWidgetPreview(campaign, variant) { + const resp = await axios.default.get(`${DBGATE_CLOUD_URL}/premium-promo-widget-preview/${campaign}/${variant}`); + return resp.data; +} + +async function getPromoWidgetList() { + const resp = await axios.default.get(`${DBGATE_CLOUD_URL}/promo-widget-list`); + return resp.data; +} + module.exports = { createDbGateIdentitySession, startCloudTokenChecking, @@ -488,4 +508,6 @@ module.exports = { readCloudTestTokenHolder, getPublicIpInfo, getPromoWidgetData, + getPromoWidgetPreview, + getPromoWidgetList, }; diff --git a/packages/api/src/utility/handleQueryStream.js b/packages/api/src/utility/handleQueryStream.js index 617991ea3..063d9bef4 100644 --- a/packages/api/src/utility/handleQueryStream.js +++ b/packages/api/src/utility/handleQueryStream.js @@ -148,6 +148,7 @@ class StreamHandler { // this.error = this.error.bind(this); this.done = this.done.bind(this); this.info = this.info.bind(this); + this.changedCurrentDatabase = this.changedCurrentDatabase.bind(this); // use this for cancelling - not implemented // this.stream = null; @@ -166,6 +167,10 @@ class StreamHandler { } } + changedCurrentDatabase(database) { + process.send({ msgtype: 'changedCurrentDatabase', database, sesid: this.sesid }); + } + recordset(columns) { if (this.rowsLimitOverflow) { return; diff --git a/packages/datalib/package.json b/packages/datalib/package.json index b82b4585a..12b52917e 100644 --- a/packages/datalib/package.json +++ b/packages/datalib/package.json @@ -3,6 +3,10 @@ "name": "dbgate-datalib", "main": "lib/index.js", "typings": "lib/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/dbgate/dbgate.git" + }, "scripts": { "build": "tsc", "test": "jest", diff --git a/packages/datalib/src/TableGridDisplay.ts b/packages/datalib/src/TableGridDisplay.ts index 9d25f44b8..1453104a3 100644 --- a/packages/datalib/src/TableGridDisplay.ts +++ b/packages/datalib/src/TableGridDisplay.ts @@ -39,7 +39,8 @@ export class TableGridDisplay extends GridDisplay { public getDictionaryDescription: DictionaryDescriptionFunc = null, isReadOnly = false, public isRawMode = false, - public currentSettings = null + public currentSettings = null, + public areReferencesAllowed = true ) { super(config, setConfig, cache, setCache, driver, dbinfo, serverVersion, currentSettings); @@ -102,11 +103,11 @@ export class TableGridDisplay extends GridDisplay { isChecked: this.isColumnChecked(col), hintColumnNames: this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null)?.columns?.map(columnName => - shortenIdentifier(`hint_${col.uniqueName}_${columnName}`, this.driver.dialect.maxIdentifierLength) + shortenIdentifier(`hint_${col.uniqueName}_${columnName}`, this.driver?.dialect?.maxIdentifierLength) ) || null, hintColumnDelimiter: this.getFkDictionaryDescription(col.isForeignKeyUnique ? col.foreignKey : null) ?.delimiter, - uniqueNameShorten: shortenIdentifier(col.uniqueName, this.driver.dialect.maxIdentifierLength), + uniqueNameShorten: shortenIdentifier(col.uniqueName, this.driver?.dialect?.maxIdentifierLength), isExpandable: !!col.foreignKey, })) || [] ); @@ -117,7 +118,7 @@ export class TableGridDisplay extends GridDisplay { if (this.isExpandedColumn(column.uniqueName)) { const table = this.getFkTarget(column); if (table) { - const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver.dialect.maxIdentifierLength); + const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver?.dialect?.maxIdentifierLength); const subcolumns = this.getDisplayColumns(table, column.uniquePath); this.addReferenceToSelect(select, parentAlias, column); @@ -130,7 +131,7 @@ export class TableGridDisplay extends GridDisplay { } addReferenceToSelect(select: Select, parentAlias: string, column: DisplayColumn) { - const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver.dialect.maxIdentifierLength); + const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver?.dialect?.maxIdentifierLength); if ((select.from.relations || []).find(x => x.alias == childAlias)) return; const table = this.getFkTarget(column); if (table && table.primaryKey) { @@ -195,11 +196,11 @@ export class TableGridDisplay extends GridDisplay { this.addReferenceToSelect( select, parentUniqueName - ? shortenIdentifier(`${parentUniqueName}_ref`, this.driver.dialect.maxIdentifierLength) + ? shortenIdentifier(`${parentUniqueName}_ref`, this.driver?.dialect?.maxIdentifierLength) : 'basetbl', column ); - const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver.dialect.maxIdentifierLength); + const childAlias = shortenIdentifier(`${column.uniqueName}_ref`, this.driver?.dialect?.maxIdentifierLength); select.columns.push( ...hintDescription.columns.map( columnName => @@ -208,7 +209,7 @@ export class TableGridDisplay extends GridDisplay { columnName, alias: shortenIdentifier( `hint_${column.uniqueName}_${columnName}`, - this.driver.dialect.maxIdentifierLength + this.driver?.dialect?.maxIdentifierLength ), source: { alias: childAlias }, } as ColumnRefExpression) @@ -248,6 +249,7 @@ export class TableGridDisplay extends GridDisplay { } processReferences(select: Select, displayedColumnInfo: DisplayedColumnInfo, options) { + if (!this.areReferencesAllowed) return; this.addJoinsFromExpandedColumns(select, this.columns, 'basetbl', displayedColumnInfo); if (!options.isExport && this.displayOptions.showHintColumns) { this.addHintsToSelect(select); diff --git a/packages/filterparser/package.json b/packages/filterparser/package.json index 1f3d32570..94dd86ef2 100644 --- a/packages/filterparser/package.json +++ b/packages/filterparser/package.json @@ -3,6 +3,10 @@ "name": "dbgate-filterparser", "main": "lib/index.js", "typings": "lib/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/dbgate/dbgate.git" + }, "scripts": { "build": "tsc", "start": "tsc --watch", diff --git a/packages/tools/src/nameTools.ts b/packages/tools/src/nameTools.ts index b63922ac9..e9bf3c26d 100644 --- a/packages/tools/src/nameTools.ts +++ b/packages/tools/src/nameTools.ts @@ -1,4 +1,5 @@ import _cloneDeep from 'lodash/cloneDeep'; +import _uniq from 'lodash/uniq'; import _isString from 'lodash/isString'; import type { ColumnInfo, @@ -75,9 +76,27 @@ export function findForeignKeyForColumn(table: TableInfo, column: ColumnInfo | s return (table.foreignKeys || []).find(fk => fk.columns.find(col => col.columnName == column.columnName)); } +export function getConflictingColumnNames(columns: ColumnInfo[]): Set { + const conflictingNames = new Set( + _uniq(columns.map(x => x.columnName).filter((item, index, arr) => arr.indexOf(item) !== index)) + ); + return conflictingNames; +} + export function makeUniqueColumnNames(res: ColumnInfo[]) { const usedNames = new Set(); + const conflictingNames = getConflictingColumnNames(res); for (let i = 0; i < res.length; i++) { + if ( + conflictingNames.has(res[i].columnName) && + res[i].pureName && + !usedNames.has(`${res[i].pureName}_${res[i].columnName}`) + ) { + res[i].columnName = `${res[i].pureName}_${res[i].columnName}`; + usedNames.add(res[i].columnName); + continue; + } + if (usedNames.has(res[i].columnName)) { let suffix = 2; while (usedNames.has(`${res[i].columnName}${suffix}`)) suffix++; diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index 0daf4c172..c583ff88a 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -21,6 +21,7 @@ export interface StreamOptions { error?: (error) => void; done?: (result) => void; info?: (info) => void; + changedCurrentDatabase?: (database: string) => void; } export type CollectionOperationInfo = diff --git a/packages/web/package.json b/packages/web/package.json index c36891158..6c4c99198 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -9,6 +9,10 @@ "build:index": "node build-index.js", "prepublishOnly": "yarn build" }, + "repository": { + "type": "git", + "url": "https://github.com/dbgate/dbgate.git" + }, "files": [ "public" ], diff --git a/packages/web/public/icon-colors.css b/packages/web/public/icon-colors.css index ccaf9fe61..25cad9a76 100644 --- a/packages/web/public/icon-colors.css +++ b/packages/web/public/icon-colors.css @@ -30,3 +30,20 @@ .color-icon-inv-red { color: var(--theme-icon-inv-red); } + +.premium-background-gradient { + background: linear-gradient(135deg, #1686c8, #8a25b1); +} + +.premium-gradient { + background: linear-gradient(135deg, #1686c8, #8a25b1); + color: white; +} + +.web-color-primary { + background: #1686c8; +} + +.web-color-secondary { + background: #8a25b1; +} diff --git a/packages/web/src/EnterLicensePage.svelte b/packages/web/src/EnterLicensePage.svelte index 79fdf6104..f3ae2ab59 100644 --- a/packages/web/src/EnterLicensePage.svelte +++ b/packages/web/src/EnterLicensePage.svelte @@ -125,8 +125,8 @@ {/if}
- For more info about DbGate licensing, you could visit dbgate.eu web or contact - us at sales@dbgate.eu + For more info about DbGate licensing, you could visit dbgate.io web or contact + us at sales@dbgate.io
{:else} diff --git a/packages/web/src/ErrorPage.svelte b/packages/web/src/ErrorPage.svelte index a24063184..42aa2f941 100644 --- a/packages/web/src/ErrorPage.svelte +++ b/packages/web/src/ErrorPage.svelte @@ -16,7 +16,7 @@
Configuration error
{#if $config?.checkedLicense?.status == 'error'} {:else if $config?.configurationError} diff --git a/packages/web/src/appobj/DatabaseAppObject.svelte b/packages/web/src/appobj/DatabaseAppObject.svelte index 671d5b64e..58a444190 100644 --- a/packages/web/src/appobj/DatabaseAppObject.svelte +++ b/packages/web/src/appobj/DatabaseAppObject.svelte @@ -468,12 +468,14 @@ await dbgateApi.executeQuery(${JSON.stringify( { divider: true }, isSqlOrDoc && + isProApp() && !connection.isReadOnly && hasPermission(`dbops/import`) && { onClick: handleImport, text: _t('database.import', { defaultMessage: 'Import' }), }, isSqlOrDoc && + isProApp() && hasPermission(`dbops/export`) && { onClick: handleExport, text: _t('database.export', { defaultMessage: 'Export' }), diff --git a/packages/web/src/buttons/FormStyledButton.svelte b/packages/web/src/buttons/FormStyledButton.svelte index 484987e1b..c117f46c7 100644 --- a/packages/web/src/buttons/FormStyledButton.svelte +++ b/packages/web/src/buttons/FormStyledButton.svelte @@ -9,6 +9,7 @@ export let title = null; export let skipWidth = false; export let outline = false; + export let colorClass = ''; function handleClick() { if (!disabled) dispatch('click'); @@ -31,6 +32,8 @@ bind:this={domButton} class:skipWidth class:outline + class={colorClass} + class:setBackgroundColor={!colorClass} /> diff --git a/packages/web/src/jsonui/JsonUiHighlight.svelte b/packages/web/src/jsonui/JsonUiHighlight.svelte new file mode 100644 index 000000000..4b083ee89 --- /dev/null +++ b/packages/web/src/jsonui/JsonUiHighlight.svelte @@ -0,0 +1,35 @@ + + +
{ + if (link) { + openWebLink(link); + } + }} +> + {text} +
+ + diff --git a/packages/web/src/jsonui/JsonUiLinkButton.svelte b/packages/web/src/jsonui/JsonUiLinkButton.svelte index fe3ac24f5..e9a00925c 100644 --- a/packages/web/src/jsonui/JsonUiLinkButton.svelte +++ b/packages/web/src/jsonui/JsonUiLinkButton.svelte @@ -4,14 +4,11 @@ export let text: string; export let link: string; - export let newTab: boolean = true; - - // very light url guard - const safe = /^(https?:)?\/\//i.test(link) || link.startsWith('/'); + export let colorClass: string = '';
- openWebLink(link)} value={text} skipWidth /> + openWebLink(link)} value={text} skipWidth {colorClass} />
diff --git a/packages/web/src/jsonui/JsonUiMarkdown.svelte b/packages/web/src/jsonui/JsonUiMarkdown.svelte new file mode 100644 index 000000000..cfe522772 --- /dev/null +++ b/packages/web/src/jsonui/JsonUiMarkdown.svelte @@ -0,0 +1,15 @@ + + +
+ +
+ + diff --git a/packages/web/src/modals/NewObjectModal.svelte b/packages/web/src/modals/NewObjectModal.svelte index 146b7939c..786fef7c1 100644 --- a/packages/web/src/modals/NewObjectModal.svelte +++ b/packages/web/src/modals/NewObjectModal.svelte @@ -95,6 +95,7 @@ title: _t('common.exportDatabase', { defaultMessage: 'Export database' }), description: _t('newObject.exportDescription', { defaultMessage: 'Export to file like CSV, JSON, Excel, or other DB' }), command: 'database.export', + isProFeature: true, testid: 'NewObjectModal_databaseExport', disabledMessage: _t('newObject.exportDisabled', { defaultMessage: 'Export is not available for current database' }), }, diff --git a/packages/web/src/stores.ts b/packages/web/src/stores.ts index 6ab382f5e..d30046e99 100644 --- a/packages/web/src/stores.ts +++ b/packages/web/src/stores.ts @@ -187,6 +187,9 @@ export const seenPremiumPromoWidget = writableWithStorage(null, 'seenPremiumProm export const cloudConnectionsStore = writable({}); +export const promoWidgetPreview = writable(null); + + export const DEFAULT_OBJECT_SEARCH_SETTINGS = { pureName: true, schemaName: false, diff --git a/packages/web/src/tabpanel/TabsPanel.svelte b/packages/web/src/tabpanel/TabsPanel.svelte index 997349c43..d38637874 100644 --- a/packages/web/src/tabpanel/TabsPanel.svelte +++ b/packages/web/src/tabpanel/TabsPanel.svelte @@ -358,6 +358,8 @@ import { handleAfterTabClick } from '../utility/changeCurrentDbByTab'; import { getBoolSettingsValue } from '../settings/settingsTools'; import NewObjectModal from '../modals/NewObjectModal.svelte'; + import { isProApp } from '../utility/proTools'; + import { openWebLink } from '../utility/simpleTools'; export let multiTabIndex; export let shownTab; @@ -583,7 +585,13 @@
-
+
{#each groupedTabs as tabGroup}
{#if !$lockedDatabaseMode} @@ -713,7 +721,7 @@ {/each}
- {#if allowSplitTab} + {#if allowSplitTab && isProApp()}
splitTab(multiTabIndex)} @@ -723,6 +731,22 @@
{/if} + + {#if !isProApp()} +
{ + openWebLink( + `https://www.dbgate.io/purchase/${isElectronAvailable() ? 'premium' : 'team-premium'}/?utm_campaign=premiumUpgradeButton` + ); + }} + title="Upgrade to Premium" + data-testid="TabsPanel_buttonUpgrade" + > + Upgrade +
+ {/if} +
showModal(NewObjectModal, { multiTabIndex })} @@ -756,6 +780,18 @@ color: var(--theme-font-2); cursor: pointer; } + .upgrade-button { + background: linear-gradient(135deg, #1686c8, #8a25b1); + border: 1px solid var(--theme-border); + border-radius: 10px; + color: white; + cursor: pointer; + font-size: 10pt; + padding: 5px; + } + .upgrade-button:hover { + background: linear-gradient(135deg, #0f5a85, #5c1870); + } .icon-button:hover { color: var(--theme-font-1); } @@ -769,6 +805,10 @@ right: 35px; bottom: 0; } + + .tabs-upgrade-button { + right: 120px; + } .tabs.can-split { right: 60px; } diff --git a/packages/web/src/tabs/QueryTab.svelte b/packages/web/src/tabs/QueryTab.svelte index ec1035461..fc9b37d06 100644 --- a/packages/web/src/tabs/QueryTab.svelte +++ b/packages/web/src/tabs/QueryTab.svelte @@ -266,9 +266,11 @@ if (sid) { apiOn(`session-done-${sid}`, handleSessionDone); apiOn(`session-closed-${sid}`, handleSessionClosed); + apiOn(`session-changedb-${sid}`, handleChangedDatabase); return () => { apiOff(`session-done-${sid}`, handleSessionDone); apiOff(`session-closed-${sid}`, handleSessionClosed); + apiOff(`session-changedb-${sid}`, handleChangedDatabase); }; } return () => {}; @@ -567,6 +569,17 @@ handleSessionDone(); }; + const handleChangedDatabase = async props => { + changeTab(tabid, tab => ({ + ...tab, + props: { + ...tab.props, + conid, + database: props.database, + }, + })); + }; + const { editorState, editorValue, setEditorData } = useEditorData({ tabid, loadFromArgs: diff --git a/packages/web/src/utility/createQuickExportMenu.ts b/packages/web/src/utility/createQuickExportMenu.ts index 6ffccfe9c..affec534c 100644 --- a/packages/web/src/utility/createQuickExportMenu.ts +++ b/packages/web/src/utility/createQuickExportMenu.ts @@ -2,11 +2,12 @@ import type { QuickExportDefinition } from 'dbgate-types'; import { currentArchive, getCurrentArchive, getExtensions } from '../stores'; import hasPermission from './hasPermission'; import { _t } from '../translations' +import { isProApp } from './proTools'; export function createQuickExportMenuItems(handler: (fmt: QuickExportDefinition) => Function, advancedExportMenuItem) { const extensions = getExtensions(); return [ - { + isProApp() && { text: _t('export.exportAdvanced', { defaultMessage : 'Export advanced...'}), ...advancedExportMenuItem, }, @@ -16,7 +17,7 @@ export function createQuickExportMenuItems(handler: (fmt: QuickExportDefinition) onClick: handler(fmt), })), { divider: true }, - { + isProApp() && { text: _t('export.currentArchive', { defaultMessage : 'Current archive'}), onClick: handler({ extension: 'jsonl', diff --git a/packages/web/src/widgets/AdminPremiumPromoWidget.svelte b/packages/web/src/widgets/AdminPremiumPromoWidget.svelte index d3f80daed..ec3c9ea16 100644 --- a/packages/web/src/widgets/AdminPremiumPromoWidget.svelte +++ b/packages/web/src/widgets/AdminPremiumPromoWidget.svelte @@ -1,14 +1,17 @@ - {#if $promoWidget?.state == 'data'} - + {#if promoWidgetData?.state == 'data'} + {/if} diff --git a/packages/web/src/widgets/StatusBar.svelte b/packages/web/src/widgets/StatusBar.svelte index aad507563..4fa3f6c1d 100644 --- a/packages/web/src/widgets/StatusBar.svelte +++ b/packages/web/src/widgets/StatusBar.svelte @@ -27,6 +27,7 @@ import { useConnectionColor } from '../utility/useConnectionColor'; import { apiCall } from '../utility/api'; import { statusBarTabInfo } from '../utility/statusBarStore'; + import { isProApp } from '../utility/proTools'; $: databaseName = $currentDatabase && $currentDatabase.name; $: connection = $currentDatabase && $currentDatabase.connection; @@ -155,7 +156,7 @@
{/if} - {#if $currentArchive && $currentArchive != 'default'} + {#if isProApp() && $currentArchive && $currentArchive != 'default'}
{#if hasPermission('widgets/database')} @@ -22,7 +23,7 @@ {#if $visibleSelectedWidget == 'history' && hasPermission('widgets/history')} {/if} -{#if $visibleSelectedWidget == 'archive' && hasPermission('widgets/archive')} +{#if $visibleSelectedWidget == 'archive' && hasPermission('widgets/archive') && isProApp()} {/if} {#if $visibleSelectedWidget == 'plugins' && hasPermission('widgets/plugins')} diff --git a/packages/web/src/widgets/WidgetIconPanel.svelte b/packages/web/src/widgets/WidgetIconPanel.svelte index e50217f70..b939e59d8 100644 --- a/packages/web/src/widgets/WidgetIconPanel.svelte +++ b/packages/web/src/widgets/WidgetIconPanel.svelte @@ -11,6 +11,7 @@ getCurrentConfig, cloudSigninTokenHolder, seenPremiumPromoWidget, + promoWidgetPreview, } from '../stores'; import mainMenuDefinition from '../../../../app/src/mainMenuDefinition'; import hasPermission from '../utility/hasPermission'; @@ -60,7 +61,7 @@ name: 'history', title: 'Query history & Closed tabs', }, - { + isProApp() && { icon: 'icon archive', name: 'archive', title: 'Archive (saved tabular data)', @@ -167,6 +168,8 @@ openWebLink(url, true); } } + + $: promoWidgetData = $promoWidgetPreview || $promoWidget;
@@ -177,7 +180,7 @@ {/if} {#each widgets .filter(x => x && hasPermission(`widgets/${x.name}`)) - .filter(x => !x.isPremiumPromo || (!isProApp() && $promoWidget?.state == 'data')) + .filter(x => !x.isPremiumPromo || (!isProApp() && promoWidgetData?.state == 'data')) // .filter(x => !x.isPremiumOnly || isProApp()) .filter(x => x.name != 'cloud-private' || $cloudSigninTokenHolder) as item}
handleChangeWidget(item.name)} > - + {#if item.isPremiumPromo && promoWidgetData?.isColoredIcon} + + {:else} + + {/if} {#if item.isPremiumPromo}
Premium
- {#if $promoWidget?.identifier != $seenPremiumPromoWidget} + {#if promoWidgetData?.identifier != $seenPremiumPromoWidget}
{/if} {/if} @@ -281,4 +292,9 @@ top: -5px; right: 5px; } + + :global(.widget-icon-panel-rounded) { + border-top-left-radius: 10px; + border-top-right-radius: 10px; + } diff --git a/plugins/dbgate-plugin-cassandra/package.json b/plugins/dbgate-plugin-cassandra/package.json index d6a916293..9a978e2a3 100644 --- a/plugins/dbgate-plugin-cassandra/package.json +++ b/plugins/dbgate-plugin-cassandra/package.json @@ -5,6 +5,10 @@ "license": "GPL-3.0", "author": "Jan Prochazka", "description": "cassandra connector for DbGate", + "repository": { + "type": "git", + "url": "https://github.com/dbgate/dbgate.git" + }, "keywords": [ "dbgate", "cassandra", diff --git a/plugins/dbgate-plugin-clickhouse/package.json b/plugins/dbgate-plugin-clickhouse/package.json index d4da7b170..badbc0cee 100644 --- a/plugins/dbgate-plugin-clickhouse/package.json +++ b/plugins/dbgate-plugin-clickhouse/package.json @@ -14,6 +14,10 @@ "dist", "icon.svg" ], + "repository": { + "type": "git", + "url": "https://github.com/dbgate/dbgate.git" + }, "scripts": { "build:frontend": "webpack --config webpack-frontend.config", "build:frontend:watch": "webpack --watch --config webpack-frontend.config", diff --git a/plugins/dbgate-plugin-mssql/src/backend/tediousDriver.js b/plugins/dbgate-plugin-mssql/src/backend/tediousDriver.js index ac4fd9e45..88c18f15e 100644 --- a/plugins/dbgate-plugin-mssql/src/backend/tediousDriver.js +++ b/plugins/dbgate-plugin-mssql/src/backend/tediousDriver.js @@ -186,7 +186,11 @@ async function tediousStream(dbhan, sql, options) { severity: 'error', }); }; + const handleDatabaseChange = database => { + options.changedCurrentDatabase(database); + }; + dbhan.client.on('databaseChange', handleDatabaseChange); dbhan.client.on('infoMessage', handleInfo); dbhan.client.on('errorMessage', handleError); const request = new tedious.Request(sql, (err, rowCount) => { diff --git a/plugins/dbgate-plugin-mysql/src/backend/drivers.js b/plugins/dbgate-plugin-mysql/src/backend/drivers.js index f684e0b84..6167b719d 100644 --- a/plugins/dbgate-plugin-mysql/src/backend/drivers.js +++ b/plugins/dbgate-plugin-mysql/src/backend/drivers.js @@ -3,6 +3,7 @@ const stream = require('stream'); const driverBases = require('../frontend/drivers'); const Analyser = require('./Analyser'); const mysql2 = require('mysql2'); +const fs = require('fs'); const { getLogger, createBulkInsertStreamBase, makeUniqueColumnNames, extractErrorLogData } = global.DBGATE_PACKAGES['dbgate-tools']; @@ -14,6 +15,7 @@ function extractColumns(fields) { if (fields) { const res = fields.map(col => ({ columnName: col.name, + pureName: col.orgTable, })); makeUniqueColumnNames(res); return res; @@ -53,6 +55,7 @@ const drivers = driverBases.map(driverBase => ({ supportBigNumbers: true, bigNumberStrings: true, dateStrings: true, + infileStreamFactory: path => fs.createReadStream(path), // TODO: test following options // multipleStatements: true, }; @@ -127,6 +130,9 @@ const drivers = driverBases.map(driverBase => ({ time: new Date(), severity: 'info', }); + if (row.stateChanges?.schema) { + options.changedCurrentDatabase(row.stateChanges.schema); + } } else { if (columns) { options.row(zipDataRow(row, columns)); diff --git a/plugins/dbgate-plugin-oracle/package.json b/plugins/dbgate-plugin-oracle/package.json index b0d0a26b7..7f3428220 100644 --- a/plugins/dbgate-plugin-oracle/package.json +++ b/plugins/dbgate-plugin-oracle/package.json @@ -7,7 +7,7 @@ "homepage": "https://dbgate.org", "repository": { "type": "git", - "url": "https://github.com/rinie/dbgate-plugin-oracle" + "url": "https://github.com/dbgate/dbgate.git" }, "author": "Rinie Kervel", "keywords": [ diff --git a/plugins/dbgate-plugin-postgres/src/backend/drivers.js b/plugins/dbgate-plugin-postgres/src/backend/drivers.js index bf75c1518..4e079f3ea 100644 --- a/plugins/dbgate-plugin-postgres/src/backend/drivers.js +++ b/plugins/dbgate-plugin-postgres/src/backend/drivers.js @@ -13,6 +13,7 @@ const { makeUniqueColumnNames, extractDbNameFromComposite, extractErrorLogData, + getConflictingColumnNames, } = global.DBGATE_PACKAGES['dbgate-tools']; let authProxy; @@ -60,7 +61,23 @@ function extractPostgresColumns(result, dbhan) { columnName: fld.name, dataTypeId: fld.dataTypeID, dataTypeName: typeIdToName[fld.dataTypeID], + tableId: fld.tableID, })); + + // const conflictingNames = getConflictingColumnNames(res); + // if (conflictingNames.size > 0) { + // const requiredTableIds = res.filter(x => conflictingNames.has(x.columnName)).map(x => x.tableId); + // const tableIdResult = await dbhan.client.query( + // `SELECT DISTINCT c.oid AS table_id, c.relname AS table_name + // FROM pg_class c + // WHERE c.oid IN (${requiredTableIds.join(',')})` + // ); + // const tableIdToTableName = _.fromPairs(tableIdResult.rows.map(cur => [cur.table_id, cur.table_name])); + // for (const col of res) { + // col.pureName = tableIdToTableName[col.tableId]; + // } + // } + makeUniqueColumnNames(res); return res; } diff --git a/workflow-templates/build-app.tpl.yaml b/workflow-templates/build-app.tpl.yaml index bfdd0bb55..beae0c799 100644 --- a/workflow-templates/build-app.tpl.yaml +++ b/workflow-templates/build-app.tpl.yaml @@ -85,9 +85,14 @@ on: # branches: # - production +permissions: + id-token: write + contents: write + jobs: build: runs-on: ${{ matrix.os }} + environment: dbgate-app strategy: fail-fast: false @@ -145,33 +150,71 @@ jobs: _if: _community if: matrix.os == 'ubuntu-22.04' uses: samuelmeuli/action-snapcraft@v1 - - name: Publish + + - name: Publish Windows + if: matrix.os == 'windows-2022' + run: | + <> + yarn run build:app + # env: + # GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish + + - name: Publish MacOS + if: matrix.os == 'macos-14' run: | <> yarn run build:app env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish - - WIN_CSC_LINK: ${{ secrets.WINCERT_2025 }} - WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_2025_PASSWORD }} - # WIN_CSC_LINK: ${{ secrets.WINCERT_CERTIFICATE }} - # WIN_CSC_KEY_PASSWORD: ${{ secrets.WINCERT_PASSWORD }} - + # GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish CSC_LINK: ${{ secrets.APPLECERT_CERTIFICATE }} CSC_KEY_PASSWORD: ${{ secrets.APPLECERT_PASSWORD }} - APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - - SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} APPLE_APP_SPECIFIC_PASSWORD: ${{secrets.APPLE_APP_SPECIFIC_PASSWORD}} + - name: Publish Linux + if: matrix.os == 'ubuntu-22.04' + run: | + <> + yarn run build:app + env: + # GH_TOKEN: ${{ secrets.GH_TOKEN }} # token for electron publish + SNAPCRAFT_STORE_CREDENTIALS: ${{secrets.SNAPCRAFT_LOGIN}} + - name: generatePadFile _if: _community_stable run: | yarn generatePadFile + - name: Azure login (OIDC) + uses: azure/login@v2 + if: matrix.os == 'windows-2022' + with: + client-id: ${{ secrets.AZURE_TC_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TC_TENANT_ID }} + allow-no-subscriptions: true + + - name: Sign Windows artifacts with Azure Trusted Signing + uses: azure/trusted-signing-action@v0 + if: matrix.os == 'windows-2022' + with: + endpoint: https://wus3.codesigning.azure.net/ + trusted-signing-account-name: DbGate + certificate-profile-name: DbGate-Release + + files-folder: <> + files-folder-filter: exe + + timestamp-rfc3161: http://timestamp.acs.microsoft.com + timestamp-digest: SHA256 + + - name: Fix YML hashes + if: matrix.os == 'windows-2022' + run: | + <> + yarn run fixYmlHashes + - name: Copy artifacts run: | mkdir artifacts diff --git a/workflow-templates/build-npm-pro.yaml b/workflow-templates/build-npm-pro.yaml index 09110cd31..ddd73729f 100644 --- a/workflow-templates/build-npm-pro.yaml +++ b/workflow-templates/build-npm-pro.yaml @@ -8,6 +8,10 @@ on: - 'v[0-9]+.[0-9]+.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+' +permissions: + id-token: write + contents: write + # on: # push: # branches: @@ -43,13 +47,17 @@ jobs: cd dbgate-merged node adjustNpmPackageJsonPremium - - name: Configure NPM token - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - cd .. - cd dbgate-merged - npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" + # - name: Configure NPM token + # env: + # NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + # run: | + # cd .. + # cd dbgate-merged + # npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" + + # Ensure npm 11.5.1 or later is installed + - name: Update npm + run: npm install -g npm@latest - name: Remove dbmodel - should be not published run: | @@ -69,33 +77,40 @@ jobs: cd dbgate-merged yarn setCurrentVersion + - name: Compute npm dist-tag + run: | + if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then + echo "NPM_TAG=alpha" >> $GITHUB_ENV + else + echo "NPM_TAG=latest" >> $GITHUB_ENV + fi - name: Publish dbgate-api-premium run: | cd .. cd dbgate-merged/packages/api - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-web-premium run: | cd .. cd dbgate-merged/packages/web - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-serve-premium run: | cd .. cd dbgate-merged/packages/serve - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-cosmosdb run: | cd .. cd dbgate-merged/plugins/dbgate-plugin-cosmosdb - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-firestore run: | cd .. cd dbgate-merged/plugins/dbgate-plugin-firestore - npm publish + npm publish --tag "$NPM_TAG" diff --git a/workflow-templates/build-npm.yaml b/workflow-templates/build-npm.yaml index a2f74f558..2c6eef85a 100644 --- a/workflow-templates/build-npm.yaml +++ b/workflow-templates/build-npm.yaml @@ -8,6 +8,10 @@ on: - 'v[0-9]+.[0-9]+.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+' +permissions: + id-token: write + contents: write + # on: # push: # branches: @@ -35,11 +39,15 @@ jobs: with: node-version: 22.x - - name: Configure NPM token - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: | - npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" + # Ensure npm 11.5.1 or later is installed + - name: Update npm + run: npm install -g npm@latest + + # - name: Configure NPM token + # env: + # NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + # run: | + # npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}" - name: yarn install run: | @@ -49,112 +57,120 @@ jobs: run: | yarn setCurrentVersion + - name: Compute npm dist-tag + run: | + if [[ "${GITHUB_REF_NAME}" =~ -alpha\. ]]; then + echo "NPM_TAG=alpha" >> $GITHUB_ENV + else + echo "NPM_TAG=latest" >> $GITHUB_ENV + fi + - name: Publish types working-directory: packages/types run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish tools working-directory: packages/tools run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish sqltree working-directory: packages/sqltree run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish api working-directory: packages/api run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish datalib working-directory: packages/datalib run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish filterparser working-directory: packages/filterparser run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish web working-directory: packages/web run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-serve working-directory: packages/serve run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbmodel working-directory: packages/dbmodel run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-csv working-directory: plugins/dbgate-plugin-csv run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-xml working-directory: plugins/dbgate-plugin-xml run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-excel working-directory: plugins/dbgate-plugin-excel run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-mssql working-directory: plugins/dbgate-plugin-mssql run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-mysql working-directory: plugins/dbgate-plugin-mysql run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-mongo working-directory: plugins/dbgate-plugin-mongo run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-postgres working-directory: plugins/dbgate-plugin-postgres run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-sqlite working-directory: plugins/dbgate-plugin-sqlite run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-redis working-directory: plugins/dbgate-plugin-redis run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-oracle working-directory: plugins/dbgate-plugin-oracle run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-clickhouse working-directory: plugins/dbgate-plugin-clickhouse run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-dbf working-directory: plugins/dbgate-plugin-dbf run: | - npm publish + npm publish --tag "$NPM_TAG" - name: Publish dbgate-plugin-cassandra working-directory: plugins/dbgate-plugin-cassandra run: | - npm publish + npm publish --tag "$NPM_TAG" diff --git a/workflow-templates/includes.tpl.yaml b/workflow-templates/includes.tpl.yaml index f5e9ef3a1..3f5086f98 100644 --- a/workflow-templates/includes.tpl.yaml +++ b/workflow-templates/includes.tpl.yaml @@ -7,7 +7,7 @@ checkout-and-merge-pro: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 11203754aad94189b565c2816d37760b15c8e07f + ref: 6195e103e1d45e4f59bade60df5dd1784f4e6c77 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro