diff --git a/.github/workflows/deploy-pr.yml b/.github/workflows/deploy-pr.yml new file mode 100644 index 00000000..860ce647 --- /dev/null +++ b/.github/workflows/deploy-pr.yml @@ -0,0 +1,54 @@ +on: + pull_request: + +name: Pull request +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Use Node.js 14.x + uses: actions/setup-node@v2 + with: + node-version: 14.x + cache: npm + + - id: install + name: install + run: npm ci + + - name: build + run: npm run build + - name: test + run: npm run test + + - name: deploy preview + env: + AWS_DEFAULT_REGION: us-east-1 + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + EXPLORER_WEB_BUCKET: ${{ secrets.EXPLORER_WEB_BUCKET }} + if: ${{ steps.install.outputs.public_path }} + run: | + npx @dcl/cdn-uploader@next \ + --bucket $EXPLORER_WEB_BUCKET \ + --local-folder build \ + --bucket-folder "${{ steps.install.outputs.public_path }}" + + - name: Find Comment + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: "github-actions[bot]" + body-includes: Test this pull request + + - name: Create or update comment + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + # Test this pull request + This branch can be previewed at ${{ steps.install.outputs.public_url }} + edit-mode: replace \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9612a6b6..ad6755f6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,20 +14,35 @@ jobs: steps: - uses: actions/checkout@master - name: Use Node.js 14.x - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: 14.x + cache: npm + + - name: set package.json version + uses: menduz/oddish-action@master + with: + deterministic-snapshot: true + only-update-versions: true + - name: install run: npm ci + - name: build run: npm run build - name: test run: npm run test - - name: Publish + + - name: publish npm package uses: menduz/oddish-action@master with: registry-url: "https://registry.npmjs.org" access: public cwd: ./build + ## use action runId instead of current date to generate snapshot numbers + deterministic-snapshot: true + ## inform gitlab after publishing to proceed with CDN propagation + gitlab-token: ${{ secrets.GITLAB_TOKEN }} + gitlab-pipeline-url: ${{ secrets.GITLAB_URL }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/package-lock.json b/package-lock.json index c20267cf..de0901f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "decentraland-explorer-website", + "name": "@dcl/explorer-website", "version": "0.0.1", "lockfileVersion": 1, "requires": true, @@ -2631,6 +2631,11 @@ "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz", "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==" }, + "@dcl/feature-flags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@dcl/feature-flags/-/feature-flags-1.0.0.tgz", + "integrity": "sha512-ucbcOWaGd5MneveJO+fUDG3GZrfNt1puCrT7GxwSwF1a7ZuRkcO2tzogBAZe53etbKIFg/kzMJ7jV1PlKgm3ug==" + }, "@dcl/kernel-interface": { "version": "1.0.0-20210722175856.commit-173aa62", "resolved": "https://registry.npmjs.org/@dcl/kernel-interface/-/kernel-interface-1.0.0-20210722175856.commit-173aa62.tgz", @@ -2670,6 +2675,11 @@ "resolved": "https://registry.npmjs.org/@dcl/unity-renderer/-/unity-renderer-1.0.7377.tgz", "integrity": "sha512-0U6F3OfTtcFUQric8mkijoW3lxPOYNxVKkKUltc4/bBuIBhz8dHZXJ3/6AzRT3776P3jS/UkFKp0ZPS/RchTTg==" }, + "@dcl/urn-resolver": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@dcl/urn-resolver/-/urn-resolver-1.2.1.tgz", + "integrity": "sha512-BI08kTJ7fWFoUGJd+fhTghzkuUBCjTtxPIvHC122GZQ98ae0FrmTUkJ4yemHwjyKIXVhWxvpqYPdhSyFcHKsYg==" + }, "@emotion/cache": { "version": "10.0.29", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", diff --git a/package.json b/package.json index 0d8d9160..8c45e780 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "decentraland-explorer-website", + "name": "@dcl/explorer-website", "version": "0.0.1", "private": true, "scripts": { @@ -34,8 +34,10 @@ ] }, "dependencies": { + "@dcl/feature-flags": "^1.0.0", "@dcl/kernel-interface": "^1.0.0-20210722175856.commit-173aa62", "@dcl/unity-renderer": "^1.0.7377", + "@dcl/urn-resolver": "^1.2.1", "decentraland-dapps": "^9.7.1", "decentraland-kernel": "^6.6.6-20210705191533.commit-894f7d2", "eth-connect": "^6.0.0", @@ -69,5 +71,6 @@ "react-test-renderer": "^16.13.1", "redux-devtools-extension": "^2.13.8", "typescript": "~3.7.2" - } + }, + "homepage": "http://localhost:3000" } diff --git a/public/index.html b/public/index.html index 09211853..2f6316d0 100644 --- a/public/index.html +++ b/public/index.html @@ -120,14 +120,7 @@ } @@ -157,7 +150,7 @@ - + - diff --git a/public/package.json b/public/package.json index ecdae275..3d680a71 100644 --- a/public/package.json +++ b/public/package.json @@ -15,5 +15,5 @@ "bugs": { "url": "https://github.com/decentraland/explorer-website/issues" }, - "homepage": "https://github.com/decentraland/explorer-website#readme" -} + "homepage": "http://localhost:3000" +} \ No newline at end of file diff --git a/scripts/hash_generator.js b/scripts/hash_generator.js index dd255585..9bf070df 100644 --- a/scripts/hash_generator.js +++ b/scripts/hash_generator.js @@ -1,7 +1,6 @@ const fs = require('fs') const path = require('path') const dotenv = require('dotenv') -const childProcess = require('child_process') let ENV_CONTENT = {} @@ -9,17 +8,26 @@ if (fs.existsSync('.env')) { Object.assign(ENV_CONTENT, dotenv.parse(fs.readFileSync('.env'))) } -const commitVersion = childProcess.execSync('git rev-parse HEAD').toString().trim() +const packageJson = JSON.parse(fs.readFileSync('./package.json').toString()) +const publicPackageJson = JSON.parse(fs.readFileSync('./public/package.json').toString()) const kernelVersion = JSON.parse(fs.readFileSync(require.resolve('decentraland-kernel/package.json'))).version const rendererVersion = JSON.parse(fs.readFileSync(require.resolve('@dcl/unity-renderer/package.json'))).version ENV_CONTENT['KERNEL_PATH'] = path.dirname(require.resolve('decentraland-kernel/package.json')) -ENV_CONTENT['REACT_APP_WEBSITE_VERSION'] = commitVersion +ENV_CONTENT['REACT_APP_WEBSITE_VERSION'] = packageJson.version ENV_CONTENT['REACT_APP_RENDERER_VERSION'] = rendererVersion ENV_CONTENT['REACT_APP_KERNEL_VERSION'] = kernelVersion -console.log('VERSIONS:', Object.entries(ENV_CONTENT), '\n') +Object.assign(ENV_CONTENT, getPublicUrls()) + +packageJson.homepage = ENV_CONTENT['PUBLIC_URL'] + +// github action outputs. Do not touch. +console.log('::set-output name=public_url::' + packageJson.homepage) +console.log('::set-output name=public_path::' + new URL(packageJson.homepage).pathname) + +console.log('VERSIONS: ', Object.entries(ENV_CONTENT), '\n') fs.writeFileSync( '.env', @@ -27,3 +35,33 @@ fs.writeFileSync( .map((e) => e[0] + '=' + JSON.stringify(e[1])) .join('\n') + '\n' ) + +publicPackageJson.homepage = packageJson.homepage +publicPackageJson.version = packageJson.version + +fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, 2)) +fs.writeFileSync('./public/package.json', JSON.stringify(publicPackageJson, null, 2)) + +function getPublicUrls() { + if (process.env.GITHUB_BASE_REF) { + // Pull request + return { + PUBLIC_URL: `https://explorer-artifacts.decentraland.org/${packageJson.name}/branch/${process.env.GITHUB_HEAD_REF}`, + REACT_APP_RENDERER_BASE_URL: ``, + REACT_APP_KERNEL_BASE_URL: `` + } + } else if (process.env.CI) { + // master/main branch, also releases + return { + PUBLIC_URL: `https://cdn.decentraland.org/${packageJson.name}/${packageJson.version}`, + REACT_APP_RENDERER_BASE_URL: ``, + REACT_APP_KERNEL_BASE_URL: `` + } + } + // localhost + return { + PUBLIC_URL: `http://localhost:3000`, + REACT_APP_RENDERER_BASE_URL: `/cdn/packages/unity-renderer/${rendererVersion}/`, + REACT_APP_KERNEL_BASE_URL: `/cdn/packages/decentraland-kernel/${kernelVersion}/` + } +} diff --git a/src/kernel-loader/index.ts b/src/kernel-loader/index.ts index abd2c765..0f02b8aa 100644 --- a/src/kernel-loader/index.ts +++ b/src/kernel-loader/index.ts @@ -10,9 +10,11 @@ import { } from '../state/actions' import { store } from '../state/redux' import { ProviderType } from 'decentraland-connect' +import { FeatureFlagsResult, fetchFlags } from '@dcl/feature-flags' +import { resolveUrlFromUrn } from '@dcl/urn-resolver' export async function authenticate(providerType: ProviderType | null) { - const provider = await getEthereumProvider(providerType, 1) + const provider = await getEthereumProvider(providerType, 1 /* mainnet */) const kernel = store.getState().kernel.kernel @@ -21,19 +23,71 @@ export async function authenticate(providerType: ProviderType | null) { kernel.authenticate(provider, providerType == null) } -declare var KERNEL_ROOT: string -declare var RENDERER_ARTIFACTS_ROOT: string +declare var globalThis: { KERNEL_BASE_URL?: string; RENDERER_BASE_URL?: string } + +globalThis.KERNEL_BASE_URL = process.env.REACT_APP_KERNEL_BASE_URL +globalThis.RENDERER_BASE_URL = process.env.REACT_APP_RENDERER_BASE_URL + +async function resolveBaseUrl(urn: string): Promise { + if (urn.startsWith('urn:')) { + const t = await resolveUrlFromUrn(urn) + if (t) { + console.log(urn, t) + return (t + '/').replace(/(\/)+$/, '/') + } + throw new Error('Cannot resolve content for URN ' + urn) + } + return (new URL(`${urn}`, global.location.toString()).toString() + '/').replace(/(\/)+$/, '/') +} + +async function getVersions(flags: FeatureFlagsResult) { + const qs = new URLSearchParams(document.location.search) + + if (qs.has('renderer')) { + globalThis.RENDERER_BASE_URL = qs.get('renderer')! + } + + if (qs.has('kernel-urn')) { + globalThis.KERNEL_BASE_URL = qs.get('kernel-urn')! + } + + if (qs.has('renderer-branch')) { + globalThis.RENDERER_BASE_URL = `https://renderer-artifacts.decentraland.org/branch/${qs.get('renderer-branch')!}` + } + + if (qs.has('kernel-branch')) { + globalThis.KERNEL_BASE_URL = `https://explorer-web.decentraland.io/@dcl/kernel/branch/${qs.get('kernel-branch')!}` + } + + if (!globalThis.KERNEL_BASE_URL) { + if (flags.variants['explorer-rollout-kernel-version']) { + const version = flags.variants['explorer-rollout-kernel-version'].name + globalThis.KERNEL_BASE_URL = `urn:decentraland:off-chain:kernel-cdn:${version}` + } + } + + if (!globalThis.RENDERER_BASE_URL) { + if (flags.variants['explorer-rollout-unity-renderer-version']) { + const version = flags.variants['explorer-rollout-unity-renderer-version'].name + globalThis.RENDERER_BASE_URL = `urn:decentraland:off-chain:unity-renderer-cdn:${version}` + } + } +} async function initKernel() { const container = document.getElementById('gameContainer') as HTMLDivElement + const flags = await fetchFlags({ applicationName: 'explorer' }) + console.log('Feature flags', flags) + await getVersions(flags) + const kernel = await injectKernel({ kernelOptions: { - baseUrl: new URL(`${KERNEL_ROOT}`, global.location.toString()).toString() + baseUrl: await resolveBaseUrl(globalThis.KERNEL_BASE_URL || `urn:decentraland:off-chain:kernel-cdn:latest`) }, rendererOptions: { container, - baseUrl: new URL(`${RENDERER_ARTIFACTS_ROOT}`, global.location.toString()).toString() + baseUrl: await resolveBaseUrl(globalThis.RENDERER_BASE_URL || `urn:decentraland:off-chain:unity-renderer-cdn:latest`) } })