diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 4f05ece694..23c2fc36eb 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -323,8 +323,14 @@ jobs: run: npx playwright merge-reports --reporter html "$RUNNER_TEMP/all-blob-reports" - name: Upload HTML report artifact - # Upload HTML report to GitHub Actions Artifacts only for pull requests from forks - if: steps.check-reports.outputs.has_reports == 'true' && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) + # Keep reports in GitHub when S3 publishing is not configured or the pull request comes from a fork. + if: >- + steps.check-reports.outputs.has_reports == 'true' && + ( + vars.AWS_REGION == '' || + vars.AWS_BUCKET_NAME == '' || + (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) + ) uses: actions/upload-artifact@v5 with: name: playwright-html-report @@ -332,7 +338,11 @@ jobs: retention-days: 7 - name: Configure AWS credentials - if: steps.check-reports.outputs.has_reports == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) + if: >- + steps.check-reports.outputs.has_reports == 'true' && + vars.AWS_REGION != '' && + vars.AWS_BUCKET_NAME != '' && + (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} @@ -341,7 +351,11 @@ jobs: - name: Upload HTML report to S3 # Upload HTML report to S3 only for pull requests from the main repository or for non-pull requests events - if: steps.check-reports.outputs.has_reports == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) + if: >- + steps.check-reports.outputs.has_reports == 'true' && + vars.AWS_REGION != '' && + vars.AWS_BUCKET_NAME != '' && + (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) run: | export "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" aws s3 cp playwright-report/ s3://${{ vars.AWS_BUCKET_NAME }}/report-${SHORT_SHA} --recursive @@ -356,4 +370,4 @@ jobs: else echo "Download the **playwright-html-report** artifact below to view the report (open \`index.html\` in a browser)." >> $GITHUB_STEP_SUMMARY fi - echo "[Read about ducks](https://animalkingdom.org/animals/ducks/)" >> $GITHUB_STEP_SUMMARY \ No newline at end of file + echo "[Read about ducks](https://animalkingdom.org/animals/ducks/)" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 21a43b0475..62972b12c2 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -64,3 +64,12 @@ jobs: build-args: | GIT_COMMIT_SHA=${{ env.SHORT_SHA }} GIT_TAG=${{ github.ref_type == 'tag' && github.ref_name || '' }} + + - name: Update Docker Hub description + if: vars.DOCKERHUB_USERNAME != '' && vars.DOCKERHUB_ORG != '' + uses: peter-evans/dockerhub-description@432a30c9e07499fd01da9f8a49f0faf9e0ca5b77 # v4 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + repository: ${{ vars.DOCKERHUB_ORG }}/blockscout-frontend + readme-filepath: ./README.md diff --git a/README.md b/README.md index af9e52c617..8f9a4f5fb3 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,18 @@ Alternatively, you can build your own docker image and run your app from that. P For more information on migrating from the previous frontend, please see the [frontend migration docs](https://docs.blockscout.com/setup/deployment/frontend-migration). +### Custom footer version links + +This image supports runtime configuration of the repository links behind the backend and frontend version labels in the footer: + +```sh +NEXT_PUBLIC_BACKEND_REPO_URL=https://github.com/my-org/blockscout +NEXT_PUBLIC_FRONTEND_REPO_URL=https://github.com/my-org/blockscout-frontend +NEXT_PUBLIC_VERSION_LINK_TYPE=release +``` + +The defaults remain the upstream Blockscout repositories with `tree` links. Set `NEXT_PUBLIC_VERSION_LINK_TYPE=release` when your fork publishes matching GitHub releases. See the [footer environment variables](https://github.com/DOS/DOScan-Frontend/blob/main/docs/ENVS.md#footer) for details. + ## Contributing See our [Contribution guide](./docs/CONTRIBUTING.md) for pull request protocol. We expect contributors to follow our [code of conduct](./CODE_OF_CONDUCT.md) when submitting code or comments. diff --git a/deploy/tools/envs-validator/schemas/ui.ts b/deploy/tools/envs-validator/schemas/ui.ts index dcc5af2092..5c3ca4bb03 100644 --- a/deploy/tools/envs-validator/schemas/ui.ts +++ b/deploy/tools/envs-validator/schemas/ui.ts @@ -204,10 +204,13 @@ const footerLinkGroupSchema: yup.ObjectSchema = yup }); export const footerSchema = yup.object({ + NEXT_PUBLIC_BACKEND_REPO_URL: yup.string().test(urlTest), + NEXT_PUBLIC_FRONTEND_REPO_URL: yup.string().test(urlTest), NEXT_PUBLIC_FOOTER_LINKS: yup .array() .json() .of(footerLinkGroupSchema), + NEXT_PUBLIC_VERSION_LINK_TYPE: yup.string().oneOf([ 'tree', 'release' ]), }); const fontFamilySchema: yup.ObjectSchema = yup diff --git a/deploy/tools/envs-validator/test/.env.base b/deploy/tools/envs-validator/test/.env.base index 17cd47e2b8..0327a84b54 100644 --- a/deploy/tools/envs-validator/test/.env.base +++ b/deploy/tools/envs-validator/test/.env.base @@ -34,6 +34,9 @@ NEXT_PUBLIC_NAVIGATION_LAYOUT=horizontal NEXT_PUBLIC_FONT_FAMILY_HEADING={'name':'Montserrat','url':'https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap'} NEXT_PUBLIC_FONT_FAMILY_BODY={'name':'Raleway','url':'https://fonts.googleapis.com/css2?family=Raleway:wght@400;500;600;700&display=swap'} NEXT_PUBLIC_FOOTER_LINKS=https://example.com +NEXT_PUBLIC_BACKEND_REPO_URL=https://github.com/blockscout/blockscout +NEXT_PUBLIC_FRONTEND_REPO_URL=https://github.com/blockscout/frontend +NEXT_PUBLIC_VERSION_LINK_TYPE=release NEXT_PUBLIC_HELIA_VERIFIED_FETCH_ENABLED=false NEXT_PUBLIC_HIDE_INDEXING_ALERT_BLOCKS=false NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=false diff --git a/docs/ENVS.md b/docs/ENVS.md index 473a2a19a1..4633643aef 100644 --- a/docs/ENVS.md +++ b/docs/ENVS.md @@ -302,9 +302,13 @@ Operator-supplied favicon override. The app ships with the generic Blockscout fa | Variable | Type | Description | Compulsoriness | Default value | Example value | Version | | --- | --- | --- | --- | --- | --- | --- | +| NEXT_PUBLIC_BACKEND_REPO_URL | `string` | Repository base URL used by the backend version link in the footer | - | `https://github.com/blockscout/blockscout` | `https://github.com/my-org/blockscout` | v2.9.5+ | +| NEXT_PUBLIC_FRONTEND_REPO_URL | `string` | Repository base URL used by the frontend version link in the footer | - | `https://github.com/blockscout/frontend` | `https://github.com/my-org/blockscout-frontend` | v2.9.5+ | | NEXT_PUBLIC_FOOTER_LINKS | `string` | URL of configuration file (`.json` format only) or file content string representation. It contains list of link groups to be displayed in the footer. See [below](#footer-links-configuration-properties) list of available properties for particular group | - | - | `https://example.com/footer_links_config.json` \| `[{'title':'My chain','links':[{'text':'About','url':'https://example.com/about'},{'text':'Contacts','url':'https://example.com/contacts'}]}]` | v1.1.1+ | +| NEXT_PUBLIC_VERSION_LINK_TYPE | `tree \| release` | Link version labels to a repository tree or a GitHub release. Commit-only frontend builds always link to the commit | - | `tree` | `release` | v2.9.5+ | The app version shown in the footer is derived from build-time ENV variables `NEXT_PUBLIC_GIT_TAG` and `NEXT_PUBLIC_GIT_COMMIT_SHA` and cannot be overwritten at run-time. +The repository targets and link type can be overwritten at run-time with the variables above. When `release` is selected, a backend value such as `v11.2.3.+commit.f64bbacb` links to `/releases/tag/v11.2.3`. #### Footer links configuration properties diff --git a/src/shell/footer/Footer.tsx b/src/shell/footer/Footer.tsx index fe284ba288..8e875bb7e0 100644 --- a/src/shell/footer/Footer.tsx +++ b/src/shell/footer/Footer.tsx @@ -32,8 +32,16 @@ import { getApiVersionUrl } from './get-api-version-url'; const MAX_LINKS_COLUMNS = 4; -const FRONT_VERSION_URL = `https://github.com/blockscout/frontend/tree/${ config.shell.footer.frontendVersion }`; -const FRONT_COMMIT_URL = `https://github.com/blockscout/frontend/commit/${ config.shell.footer.frontendCommit }`; +const FRONT_VERSION_URL = config.shell.footer.frontendVersion ? + getApiVersionUrl( + config.shell.footer.frontendVersion, + config.shell.footer.frontendRepoUrl, + config.shell.footer.versionLinkType, + ) : + undefined; +const FRONT_COMMIT_URL = `${ config.shell.footer.frontendRepoUrl.replace(/\/+$/, '') }/commit/${ + config.shell.footer.frontendCommit +}`; const Footer = () => { @@ -44,7 +52,11 @@ const Footer = () => { refetchOnMount: false, }, }); - const apiVersionUrl = getApiVersionUrl(backendVersionData?.backend_version ?? undefined); + const apiVersionUrl = getApiVersionUrl( + backendVersionData?.backend_version ?? undefined, + config.shell.footer.backendRepoUrl, + config.shell.footer.versionLinkType, + ); const BLOCKSCOUT_LINKS = [ { diff --git a/src/shell/footer/config.ts b/src/shell/footer/config.ts index 30c905a343..aa5930c558 100644 --- a/src/shell/footer/config.ts +++ b/src/shell/footer/config.ts @@ -3,9 +3,12 @@ import { getEnvValue, getExternalAssetFilePath } from 'src/config/utils/envs'; const config = Object.freeze({ + backendRepoUrl: getEnvValue('NEXT_PUBLIC_BACKEND_REPO_URL') || 'https://github.com/blockscout/blockscout', + frontendRepoUrl: getEnvValue('NEXT_PUBLIC_FRONTEND_REPO_URL') || 'https://github.com/blockscout/frontend', links: getExternalAssetFilePath('NEXT_PUBLIC_FOOTER_LINKS'), frontendVersion: getEnvValue('NEXT_PUBLIC_GIT_TAG'), frontendCommit: getEnvValue('NEXT_PUBLIC_GIT_COMMIT_SHA'), + versionLinkType: getEnvValue('NEXT_PUBLIC_VERSION_LINK_TYPE') === 'release' ? 'release' : 'tree', }); export default config; diff --git a/src/shell/footer/get-api-version-url.spec.ts b/src/shell/footer/get-api-version-url.spec.ts new file mode 100644 index 0000000000..c3fb4e932d --- /dev/null +++ b/src/shell/footer/get-api-version-url.spec.ts @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: LicenseRef-Blockscout + +import { describe, expect, it } from 'vitest'; + +import { getApiVersionUrl } from './get-api-version-url'; + +describe('getApiVersionUrl', () => { + it('keeps the upstream commit link behavior by default', () => { + expect(getApiVersionUrl('v11.2.3.+commit.f64bbacb')).toBe( + 'https://github.com/blockscout/blockscout/commit/f64bbacb', + ); + }); + + it('keeps the upstream tree link behavior by default', () => { + expect(getApiVersionUrl('v11.2.3')).toBe( + 'https://github.com/blockscout/blockscout/tree/v11.2.3', + ); + }); + + it('builds a release link for a custom repository and strips commit metadata', () => { + expect(getApiVersionUrl( + 'v11.2.3.+commit.f64bbacb', + 'https://github.com/DOS/DOScan/', + 'release', + )).toBe('https://github.com/DOS/DOScan/releases/tag/v11.2.3'); + }); + + it('returns undefined when the version is missing', () => { + expect(getApiVersionUrl(undefined)).toBeUndefined(); + }); +}); diff --git a/src/shell/footer/get-api-version-url.tsx b/src/shell/footer/get-api-version-url.tsx index 6a386fc916..517eeffc4f 100644 --- a/src/shell/footer/get-api-version-url.tsx +++ b/src/shell/footer/get-api-version-url.tsx @@ -1,15 +1,26 @@ // SPDX-License-Identifier: LicenseRef-Blockscout -export function getApiVersionUrl(version: string | undefined): string | undefined { +type VersionLinkType = 'release' | 'tree'; + +export function getApiVersionUrl( + version: string | undefined, + repoUrl = 'https://github.com/blockscout/blockscout', + linkType: VersionLinkType = 'tree', +): string | undefined { if (!version) { return; } const [ tag, commit ] = version.split('.+commit.'); + const normalizedRepoUrl = repoUrl.replace(/\/+$/, ''); + + if (linkType === 'release') { + return `${ normalizedRepoUrl }/releases/tag/${ tag }`; + } if (commit) { - return `https://github.com/blockscout/blockscout/commit/${ commit }`; + return `${ normalizedRepoUrl }/commit/${ commit }`; } - return `https://github.com/blockscout/blockscout/tree/${ tag }`; + return `${ normalizedRepoUrl }/tree/${ tag }`; }