diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index bacadccbf1e..0a4d1b1fd57 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -1,10 +1,15 @@ name: Mirror Image on: + workflow_call: + inputs: + version: + required: true + type: string workflow_dispatch: inputs: version: - description: "Image tag" + description: 'Image tag' required: true type: string diff --git a/.github/workflows/publish_image.yml b/.github/workflows/publish_image.yml index fb21fd49d43..f57fd2515d3 100644 --- a/.github/workflows/publish_image.yml +++ b/.github/workflows/publish_image.yml @@ -14,29 +14,39 @@ on: type: string jobs: - publish: + settings: runs-on: ubuntu-latest - permissions: - contents: read - packages: write + outputs: + image_version: ${{ steps.meta.outputs.version }} steps: - id: meta uses: docker/metadata-action@v4 with: images: | supabase/studio - public.ecr.aws/supabase/studio - ghcr.io/supabase/studio flavor: | latest=false tags: | type=ref,event=tag - type=sha,prefix={{date 'YYYYMMDD'}},enable=${{ github.ref_type == 'branch' }} - type=raw,value=${{ inputs.version }},enable=${{ github.event_name != 'push' }} + type=sha,prefix={{date 'YYYYMMDD'}}-,enable=${{ github.event_name == 'push' && github.ref_type == 'branch' }} + type=raw,value=${{ inputs.version }},enable=${{ github.event_name == 'workflow_dispatch' }} - - uses: docker/setup-qemu-action@v2 + release_x86: + needs: settings + runs-on: ubuntu-latest + timeout-minutes: 120 + env: + arch: amd64 + outputs: + image_digest: ${{ steps.build.outputs.digest }} + steps: + - id: meta + uses: docker/metadata-action@v4 with: - platforms: amd64,arm64 + images: | + supabase/studio + tags: | + type=raw,value=${{ needs.settings.outputs.image_version }}_${{ env.arch }} - uses: docker/setup-buildx-action@v2 @@ -46,27 +56,86 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Login to ECR - uses: docker/login-action@v2 - with: - registry: public.ecr.aws - username: ${{ secrets.PROD_ACCESS_KEY_ID }} - password: ${{ secrets.PROD_SECRET_ACCESS_KEY }} - - - name: Login to GHCR - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - uses: docker/build-push-action@v3 + - id: build + uses: docker/build-push-action@v3 with: push: true context: '{{defaultContext}}' file: studio/Dockerfile target: production - platforms: linux/amd64,linux/arm64 + platforms: linux/${{ env.arch }} tags: ${{ steps.meta.outputs.tags }} cache-from: type=gha cache-to: type=gha,mode=max + + release_arm: + needs: settings + runs-on: arm-runner + timeout-minutes: 120 + env: + arch: arm64 + outputs: + image_digest: ${{ steps.build.outputs.digest }} + steps: + - uses: actions/checkout@v3 + + - id: meta + uses: docker/metadata-action@v4 + with: + images: | + supabase/studio + tags: | + type=raw,value=${{ needs.settings.outputs.image_version }}_${{ env.arch }} + + - uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - uses: docker/setup-buildx-action@v2 + with: + driver: docker + driver-opts: | + image=moby/buildkit:master + network=host + + - id: build + uses: docker/build-push-action@v3 + with: + push: true + context: . + file: studio/Dockerfile + target: production + platforms: linux/${{ env.arch }} + tags: ${{ steps.meta.outputs.tags }} + no-cache: true + + merge_manifest: + needs: + - settings + - release_x86 + - release_arm + runs-on: ubuntu-latest + steps: + - uses: docker/setup-buildx-action@v2 + + - uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Merge multi-arch manifests + run: | + docker buildx imagetools create -t supabase/studio:${{ needs.settings.outputs.image_version }} \ + supabase/studio@${{ needs.release_x86.outputs.image_digest }} \ + supabase/studio@${{ needs.release_arm.outputs.image_digest }} + + publish: + needs: + - settings + - merge_manifest + # Call workflow explicitly because events from actions cannot trigger more actions + uses: ./.github/workflows/mirror.yml + with: + version: ${{ needs.settings.outputs.image_version }} + secrets: inherit diff --git a/DEVELOPERS.md b/DEVELOPERS.md index 9d769ccb70e..0281b1b0bd7 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -8,6 +8,7 @@ - [Running turborepo](#running-turborepo) - [Shared components](#shared-components) - [Installing packages](#installing-packages) + - [New Supabase docs](#new-supabase-docs) 3. [Create a pull request](#create-a-pull-request) - [Common tasks](#common-tasks) @@ -106,6 +107,14 @@ For example: You do not need to install `devDependencies` in each workspace. These can all be installed in the root package. +#### New Supabase docs + +Following the changes to the [Supabase docs](https://supabase.com/blog/new-supabase-docs-built-with-nextjs) the following is needed to run the new docs locally: + +- Inside of `apps/docs` create a `.env.local` file with the following: `NEXT_PUBLIC_NEW_DOCS=true` + +Now when you run a local devlopment docs server you will see the new docs site. + --- ## Create a pull request diff --git a/README.md b/README.md index 4c35921e1a5..4a6e2f223da 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ Our approach for client libraries is modular. Each sub-library is a standalone i - gotrue-java - - - + storage-java - diff --git a/apps/docs/components/DocSearch.tsx b/apps/docs/components/DocSearch.tsx index 38c48a75396..19e1c85be8b 100644 --- a/apps/docs/components/DocSearch.tsx +++ b/apps/docs/components/DocSearch.tsx @@ -20,7 +20,6 @@ function SearchProviderContent({ children }: any) { const router = useRouter() const [isOpen, setIsOpen] = useState(false) const [initialQuery, setInitialQuery] = useState(null) - const onOpen = useCallback(() => { setIsOpen(true) }, [setIsOpen]) @@ -85,6 +84,7 @@ function SearchProviderContent({ children }: any) { hitComponent={Hit} transformItems={(items) => { return items.map((item, index) => { + console.log('item', item) // We transform the absolute URL into a relative URL to // leverage Next's preloading. const a = document.createElement('a') @@ -96,7 +96,8 @@ function SearchProviderContent({ children }: any) { ...item, url: `${a.pathname}${hash}`, __is_result: () => true, - __is_parent: () => item.type === 'lvl1' && items.length > 1 && index === 0, + __is_parent: () => item.type === 'lvl1' && index === 0, + __is_guide: () => item.hierarchy.lvl0 === 'Guides', __is_child: () => item.type !== 'lvl1' && items.length > 1 && @@ -129,6 +130,7 @@ function Hit({ hit, children }) { 'DocSearch-Hit--FirstChild': hit.__is_first?.(), 'DocSearch-Hit--LastChild': hit.__is_last?.(), 'DocSearch-Hit--Child': hit.__is_child?.(), + 'DocSearch-Hit--Guide': hit.__is_guide?.(), })} > {children} diff --git a/apps/docs/components/Footer/DarkModeToggle.tsx b/apps/docs/components/Footer/DarkModeToggle.tsx deleted file mode 100644 index 04f9d225854..00000000000 --- a/apps/docs/components/Footer/DarkModeToggle.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { useTheme } from 'common/Providers' -import { IconSun, IconMoon } from '@supabase/ui' - -function DarkModeToggle() { - const { isDarkMode, toggleTheme } = useTheme() - - const toggleDarkMode = () => { - localStorage.setItem('supabaseDarkMode', (!isDarkMode).toString()) - toggleTheme() - - const key = localStorage.getItem('supabaseDarkMode') - document.documentElement.className = key === 'true' ? 'dark' : '' - } - - return ( -
- - - -
- ) -} - -export default DarkModeToggle diff --git a/apps/docs/components/Footer/index.tsx b/apps/docs/components/Footer/index.tsx deleted file mode 100644 index 01424c906f5..00000000000 --- a/apps/docs/components/Footer/index.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import { Badge } from 'ui' -import Link from 'next/link' -import Image from 'next/image' -import FooterLinks from 'data/footer.json' -import DarkModeToggle from './DarkModeToggle' -import { useTheme } from 'common/Providers' -import * as supabaseLogoWordmarkDark from 'common/assets/images/supabase-logo-wordmark--dark.png' -import * as supabaseLogoWordmarkLight from 'common/assets/images/supabase-logo-wordmark--light.png' - -const Footer = () => { - const { isDarkMode } = useTheme() - - return ( - - ) -} - -export default Footer diff --git a/apps/docs/components/FooterHelpCallout.tsx b/apps/docs/components/FooterHelpCallout.tsx index 82f1a03c683..2eb6421dc4c 100644 --- a/apps/docs/components/FooterHelpCallout.tsx +++ b/apps/docs/components/FooterHelpCallout.tsx @@ -1,11 +1,13 @@ const FooterHelpCallout = () => { return ( -
-
Need some help?
-

- Not to worry, our specialist engineers are here to help. Submit a support ticket through the{' '} - Dashboard. -

+
+
+
Need some help?
+

+ Not to worry, our specialist engineers are here to help. Submit a support ticket through + the Dashboard. +

+
) } diff --git a/apps/docs/components/Navigation/Footer.tsx b/apps/docs/components/Navigation/Footer.tsx new file mode 100644 index 00000000000..3d85d66b3cb --- /dev/null +++ b/apps/docs/components/Navigation/Footer.tsx @@ -0,0 +1,56 @@ +import Image from 'next/image' +import Link from 'next/link' +import { Button, IconGitHub, IconTwitter } from '~/../../packages/ui' +import footerData from '~/data/footer.json' +import { useTheme } from 'common/Providers' + +const Footer = () => { + const { isDarkMode } = useTheme() + return ( +
+
+
+
+ Supabase 2022 + — + {footerData.map((item) => ( + + {item.title} + + ))} +
+
+ + +
+
+
+ ) +} + +export default Footer diff --git a/apps/docs/components/Navigation/Navigation.constants.ts b/apps/docs/components/Navigation/Navigation.constants.ts index a9750d6037c..53b76960443 100644 --- a/apps/docs/components/Navigation/Navigation.constants.ts +++ b/apps/docs/components/Navigation/Navigation.constants.ts @@ -102,6 +102,7 @@ export const menuItems: NavMenu = { { name: 'Login with Twitch', url: '/guides/auth/auth-twitch', items: [] }, { name: 'Login with Twitter', url: '/guides/auth/auth-twitter', items: [] }, { name: 'Login with WorkOS', url: '/guides/auth/auth-workos', items: [] }, + { name: 'Login with Zoom', url: '/guides/auth/auth-zoom', items: [] }, { name: 'Phone Auth with Twilio', url: '/guides/auth/auth-twilio', items: [] }, { name: 'Phone Auth with Vonage', url: '/guides/auth/auth-vonage', items: [] }, { @@ -265,6 +266,7 @@ export const menuItems: NavMenu = { url: '/guides/platform/migrating-and-upgrading-projects', items: [], }, + { name: 'Network Restrictions', url: '/guides/platform/network-restrictions', items: [] }, { name: 'Performance Tuning', url: '/guides/platform/performance', items: [] }, { name: 'Permissions', url: '/guides/platform/permissions', items: [] }, { name: 'Production Readiness', url: '/guides/platform/going-into-prod', items: [] }, diff --git a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx index 8101690b2f4..a3cd6b3499b 100644 --- a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx @@ -63,6 +63,12 @@ const home = [ href: '/guides/resources', level: 'resources', }, + { + label: 'Self-Hosting', + icon: '/img/icons/menu/platform', + href: '/guides/self-hosting', + level: 'self_hosting', + }, { label: 'Integrations', icon: '/img/icons/menu/integrations', diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts index dc627058192..b5b21af6420 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts @@ -240,6 +240,12 @@ export const SocialLoginItems = [ url: '/guides/auth/social-login/auth-workos', items: [], }, + { + name: 'Zoom', + icon: '/docs/img/icons/zoom-icon', + url: '/guides/auth/social-login/auth-zoom', + items: [], + }, ] export const PhoneLoginsItems = [ @@ -247,20 +253,20 @@ export const PhoneLoginsItems = [ name: 'MessageBird SMS Login', icon: '/docs/img/icons/messagebird-icon', linkDescription: 'Communication between businesses and their customers — across any channel.', - url: '/guides/auth/passwordless-login/phone-sms-otp-messagebird', + url: '/guides/auth/phone-login/messagebird', items: [], }, { name: 'Twilio SMS Login', icon: '/docs/img/icons/twilio-icon', - url: '/guides/auth/passwordless-login/phone-sms-otp-twilio', + url: '/guides/auth/phone-login/twilio', linkDescription: 'Customer engagement platform used by hundreds of thousands of businesses.', items: [], }, { name: 'Vonage SMS Login', icon: '/docs/img/icons/vonage-icon', - url: '/guides/auth/passwordless-login/phone-sms-otp-vonage', + url: '/guides/auth/phone-login/vonage', linkDescription: 'Vonage is a communication platform as a service (CPaaS) provider for consumers and businesses.', items: [], @@ -281,24 +287,18 @@ export const auth = { url: undefined, items: [ { name: 'Email Login', url: '/guides/auth/auth-email', items: [] }, + { name: 'Magic Link Login', url: '/guides/auth/auth-magic-link', items: [] }, { - name: 'Passwordless Login', - url: '/guides/auth/passwordless-login', - items: [ - { - name: 'Magic Link Login', - icon: '', - url: '/guides/auth/passwordless-login/email-otp-magic-link', - items: [], - }, - ...PhoneLoginsItems, - ], + name: 'Phone Login', + url: '/guides/auth/phone-login', + items: [...PhoneLoginsItems], }, { name: 'Social Login', url: '/guides/auth/social-login', items: [...SocialLoginItems], }, + { name: 'Email Templates', url: '/guides/auth/auth-email-templates', items: [] }, ], }, { @@ -469,12 +469,14 @@ export const platform = { items: [ { name: 'Compute Add-ons', url: '/guides/platform/compute-add-ons', items: [] }, { name: 'Custom Domains', url: '/guides/platform/custom-domains', items: [] }, + { name: 'Database Backups', url: '/guides/platform/backups', items: [] }, ], }, { name: 'Platform Management', url: undefined, items: [ + { name: 'Access Control', url: '/guides/platform/access-control', items: [] }, { name: 'Database Usage', url: '/guides/platform/database-usage', items: [] }, { name: 'Logging', url: '/guides/platform/logs', items: [] }, { name: 'Metrics', url: '/guides/platform/metrics', items: [] }, @@ -483,10 +485,29 @@ export const platform = { url: '/guides/platform/migrating-and-upgrading-projects', items: [], }, + { name: 'Network Restrictions', url: '/guides/platform/network-restrictions', items: [] }, { name: 'Performance Tuning', url: '/guides/platform/performance', items: [] }, { name: 'Permissions', url: '/guides/platform/permissions', items: [] }, ], }, + { + name: 'Single sign-on', + url: undefined, + items: [ + { + name: 'Enable SSO for your organization', + url: '/guides/platform/sso', + items: [], + }, + { name: 'SSO with Azure AD', url: '/guides/platform/sso/azure', items: [] }, + { + name: 'SSO with Google Workspace', + url: '/guides/platform/sso/gsuite', + items: [], + }, + { name: 'SSO with Okta', url: '/guides/platform/sso/okta', items: [] }, + ], + }, { name: 'Go-live Checklist', url: undefined, @@ -500,7 +521,8 @@ export const resources = { label: 'Resources', url: '/guides/resources', items: [ - { name: 'Examples', url: '/guides/resources/examples', items: [] }, + // removing until the examples page is reworked + // { name: 'Examples', url: '/guides/resources/examples', items: [] }, { name: 'Glossary', url: '/guides/resources/glossary', items: [] }, { name: 'Migrate to Supabase', @@ -512,8 +534,8 @@ export const resources = { items: [], }, { - name: 'Firebase Data', - url: '/guides/resources/migrating-to-supabase/firebase-data', + name: 'Firestore Data', + url: '/guides/resources/migrating-to-supabase/firestore-data', items: [], }, { @@ -543,37 +565,7 @@ export const resources = { }, { name: 'Managing Environments', - url: '/guides/cli/managing-environments', - items: [], - }, - ], - }, - { - name: 'Self-Hosting', - items: [ - { name: 'Overview', url: '/guides/resources/self-hosting', items: [] }, - { name: 'Docker', url: '/guides/resources/self-hosting/docker', items: [] }, - ], - }, - { - name: 'Self-Hosting Reference', - items: [ - { - name: 'Auth Server', - url: '/reference/self-hosting-auth/introduction', - icon: '/img/icons/menu/reference-auth', - items: [], - }, - { - name: 'Storage Server', - url: '/reference/self-hosting-storage/introduction', - icon: '/img/icons/menu/reference-storage', - items: [], - }, - { - name: 'Realtime Server', - url: '/reference/self-hosting-realtime/introduction', - icon: '/img/icons/menu/reference-realtime', + url: '/guides/resources/supabase-cli/managing-environments', items: [], }, ], @@ -581,12 +573,34 @@ export const resources = { ], } -export const selfHosting = { - label: 'Self-Hosting', +export const self_hosting = { + title: 'Self-Hosting', + icon: 'resources', url: '/guides/self-hosting', items: [ - { name: 'Overview', url: '/guides/hosting/overview', items: [] }, - { name: 'Docker', url: '/guides/hosting/docker', items: [] }, + { name: 'Overview', url: '/guides/self-hosting', items: [] }, + { name: 'Self-Hosting with Docker', url: '/guides/self-hosting/docker', items: [] }, + { + name: 'Auth Server', + items: [ + { name: 'Reference', url: '/reference/self-hosting-auth/introduction', items: [] }, + { name: 'Configuration', url: '/guides/self-hosting/auth/config', items: [] }, + ], + }, + { + name: 'Storage Server', + items: [ + { name: 'Reference', url: '/reference/self-hosting-storage/introduction', items: [] }, + { name: 'Configuration', url: '/guides/self-hosting/storage/config', items: [] }, + ], + }, + { + name: 'Realtime Server', + items: [ + { name: 'Reference', url: '/reference/self-hosting-realtime/introduction', items: [] }, + { name: 'Configuration', url: '/guides/self-hosting/realtime/config', items: [] }, + ], + }, ], } @@ -654,6 +668,11 @@ export const integrations = { { name: 'Plasmic', url: '/guides/integrations/plasmic', items: [] }, ], }, + { + name: 'Messaging', + url: undefined, + items: [{ name: 'OneSignal', url: '/guides/integrations/onesignal', items: [] }], + }, ], } diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx index ba106fdb574..ff6adccfad5 100644 --- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx @@ -104,6 +104,9 @@ const SideNav = () => { case url.includes(`/docs/guides/resources`) && url: menuState.setMenuLevelId('resources') break + case url.includes(`/docs/guides/self-hosting`) && url: + menuState.setMenuLevelId('self_hosting') + break case url.includes(`/docs/guides/integrations`) && url: menuState.setMenuLevelId('integrations') break diff --git a/apps/docs/components/Navigation/NavigationMenu/TopNavBarRef.tsx b/apps/docs/components/Navigation/NavigationMenu/TopNavBarRef.tsx index 6fcae17712d..d5a706d6cb2 100644 --- a/apps/docs/components/Navigation/NavigationMenu/TopNavBarRef.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/TopNavBarRef.tsx @@ -2,19 +2,7 @@ import Image from 'next/image' import Link from 'next/link' import { useRouter } from 'next/router' import { FC, useEffect, useState } from 'react' -import { - Badge, - Button, - Dropdown, - IconCommand, - IconMenu, - IconMessageSquare, - IconMoon, - IconSearch, - IconSun, - Input, - Listbox, -} from 'ui' +import { Button, IconCommand, IconGitHub, IconMoon, IconSearch, IconSun } from 'ui' import { SearchButton } from '~/components/DocSearch' import { REFERENCES } from '~/components/Navigation/Navigation.constants' import { useTheme } from 'common/Providers' @@ -134,7 +122,7 @@ const TopNavBarRef: FC = () => { target="_blank" rel="noreferrer noopener" > - Main site + Supabase.com +