Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storybook Gitlab Pages: script importing from wrong URL resulting in CORS errors

I am trying to use Gitlab CI to build and host a storybook page when I push an update to any branch. Here is the current CI script:

CI Script

image: node:16

stages:
  - setup
  - build-and-test
  - deployment
  - pages

# stage: setup

setup:
  stage: setup
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
  artifacts:
    paths:
      - node_modules/
  script:
    - yarn

# stage: build-and-test (here I run linter, unit tests, and everything I want to build or test)

build:
  stage: build-and-test
  artifacts:
    paths:
      - dist/
  script:
    - yarn build

storybook:
  stage: build-and-test
  artifacts:
    expire_in: 2 weeks
    when: always
    paths:
      - storybook/
  script:
    - yarn build-storybook --output-dir storybook

# stage: deployment (here I deploy my app to specific stages or other artefacts like storybook)

deploy-storybook:
  stage: deployment
  script:
    - echo "Enjoy the day. 🥳 Every job needs a script, but this job was just created to configure an environment."
  environment:
    name: storybook/$CI_COMMIT_REF_SLUG
    url: https://<my_username>.gitlab.io/<my_project>/$CI_COMMIT_REF_SLUG/storybook/
    on_stop: remove-storybook
  only:
    - branches

remove-storybook:
  stage: deployment
  cache:
    key: 'my-storybook'
    paths:
      - public
  script:
    - rm -rf "public/$CI_COMMIT_REF_SLUG/storybook"
  when: manual
  variables:
    GIT_STRATEGY: none # needed to prevent "Couldn't find remote ref" error
  environment:
    name: storybook/$CI_COMMIT_REF_SLUG
    action: stop

# stage: pages (the stage name is custom, but the job NEEDS to be named pages)

pages:
  stage: pages
  cache:
    key: 'my-storybook'
    paths:
      - public
  script:
    - if [ "$CI_COMMIT_REF_NAME" = "main" ]; then
      mkdir -p public;
      touch public/index.html;
      echo "<!DOCTYPE HTML><script>window.location.href = 'https://<my_username>.gitlab.io/<my_project>/main/storybook'</script>" > public/index.html;
      fi;
    - rm -rf "public/$CI_COMMIT_REF_SLUG"
    - mkdir -p "public/$CI_COMMIT_REF_SLUG";
    - mv storybook "public/$CI_COMMIT_REF_SLUG"
  artifacts:
    paths:
      - public

This compiles as intended but has errors in console when viewed:

iframe.html:1 Access to script at 'https://gitlab.com/oauth/authorize?client_id=<my_client_id>&redirect_uri=https://projects.gitlab.io/auth&response_type=code&state=AFyDa1QTpsd9qXqSzdoy4w==&scope=api' (redirected from 'https://<my_username>.gitlab.io/assets/iframe.8696a5de.js') from origin 'https://<my_username>.gitlab.io' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
iframe.html:374          GET https://gitlab.com/oauth/authorize?client_id=<my_client_id>&redirect_uri=https://projects.gitlab.io/auth&response_type=code&state=AFyDa1QTpsd9qXqSzdoy4w==&scope=api net::ERR_FAILED 302

The relevant section of https://<my_username>.gitlab.io/<project_name>/<branch>/storybook/assets/iframe.html:

<head>
  ...
  <script defer src="/node_modules/@fortawesome/fontawesome-free/js/all.min.js"></script>

  <!-- iframe.html:374 -->
  <script type="module" crossorigin src="/assets/iframe.8696a5de.js"></script>

  <link rel="stylesheet" href="/assets/iframe.0f83afa4.css">
  ...
</head>

.storybook/main.cjs

const { resolve } = require("path");
const { typescript: preprocessTS } = require("svelte-preprocess");
const { loadConfigFromFile, mergeConfig } = require("vite");

module.exports = {
  "stories": [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx|svelte)"
  ],
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions",
    "@storybook/addon-svelte-csf"
  ],
  "framework": "@storybook/svelte",
  "core": {
    "builder": "@storybook/builder-vite"
  },
  "svelteOptions": {
    "preprocess": import("../svelte.config.js").preprocess
  },
  svelteOptions: {
    preprocess: [
      preprocessTS(),
    ],
  },
  async viteFinal(config, { configType }) {
    const { config: userConfig } = await loadConfigFromFile(
      resolve(__dirname, "../vite.config.ts")
    );

    return mergeConfig(config, {
      ...userConfig,
      // manually specify plugins to avoid conflict
      plugins: []
    });
  }
}

Question

What can I do to fix this script import error? I think the generated url in the script tag is wrong, and should instead be something similar to https://<my_username>.gitlab.io/<project_name>/<branch>/storybook/assets/iframe.8696a5de.js (instead of the current https://<my_username>.gitlab.io/assets/iframe.8696a5de.js). Is there any way I can edit the CI to edit the root URL?

If that would not work, why not, and what would work instead?

like image 402
LaytonGB Avatar asked Sep 03 '25 17:09

LaytonGB


1 Answers

I have found a workaround but I would not consider it a proper solution. If you are stuck with this problem, the following does work:

I used Regular Expression replacement in the GitLab CI to correct the src and href paths of all links in the built index.html and iframe.html files. The exact code I used is as follows:

- sed -i -E "s/((src|href)=\")\/?/\1.\//g" public/$CI_COMMIT_REF_SLUG/storybook/index.html
- sed -i -E "s/((src|href)=\")\/?/\1.\//g" public/$CI_COMMIT_REF_SLUG/storybook/iframe.html

This change is necessary for 2 reasons:

  • The page hosted includes the repository name (eg, <user>.gitlab.io/<repo>/). Any links from this page starting in a slash will search for their resources at <user>.gitlab.io/ and the resource won't be there, but the system never gets that far (see below).
  • Gitlab requires authentication for any non-relative resource paths so the resource will be blocked.

The regex replacement fixes these problems by replacing any resource written as path/name.ext or /path/name.ext with ./path/name.ext which in my case works and shall hopefully work for whoever needs this.

like image 169
LaytonGB Avatar answered Sep 06 '25 18:09

LaytonGB