Загрузка данных


workflow:
  rules:
    - if: $CI_COMMIT_TAG
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
      when: never

include:
  - project: 'moex-admins/moex-dop/moex-dop-cicd'
    ref: 'itt_template'
    file: '/teams/itt/mr_approval.yml'

  - project: 'moex-admins/moex-dop/moex-dop-cicd'
    ref: 'itt_template'
    file: '/teams/itt/sonar-nodejs.yml'
    rules:
      - if: $CI_PIPELINE_SOURCE == "pipeline"
        when: never
      - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
      - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      - if: $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^bugfix\/.*$/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^release\/.*$/
      - if: $CI_COMMIT_REF_NAME =~ /^release\/.*$/ && $CI_COMMIT_BEFORE_SHA == "0000000000000000000000000000000000000000"

stages:
  - build
  - test
  - sast
  - publish

variables:
  PACKAGE_NAME: moex-chart
  SONARQUBE_PROJECT_KEY: info-trade-terminal_${CI_PROJECT_NAME}
  SONARQUBE_PROJECT_NAME: ${CI_PROJECT_NAME}
  SONARQUBE_COVERAGE_REPORT_USE: 'true'
  TEST_ENABLED: 'true'
  SONARQUBE_ENABLED: 'true'
  SONARSCANNER_IMAGE: moex-docker-static-hosted-nexus-dev.tech.moex.com/sonarsource/sonar-scanner-cli:5.0

build:
  stage: build
  image: moex-docker-static-hosted-nexus-dev.tech.moex.com/node:22.11.0-bookworm-jq
  script:
    - |
      npm config set loglevel verbose
      npm config set ignore-scripts true
      rm -f package-lock.json

      VERSION=${CI_COMMIT_TAG:-"0.0.0"}
      npm version $VERSION --no-git-tag-version || true

      npm install
      npm run build:lib:js
      npm run build:lib:types
      npm pack
      mkdir -p pack-result
      mv $PACKAGE_NAME-*.tgz pack-result
  artifacts:
    paths:
      - pack-result/
  rules:
    - if: $CI_COMMIT_TAG
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

test:
  stage: test
  image: moex-docker-static-hosted-nexus-dev.tech.moex.com/node:22.11.0-bookworm-jq
  script:
    - |
      npm config set loglevel verbose
      npm config set ignore-scripts true

      npm install
      npm run coverage

      test -f coverage/lcov.info
  artifacts:
    paths:
      - coverage/lcov.info
    expire_in: 1 day
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event' && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

publish:
  stage: publish
  image: moex-docker-static-hosted-nexus-dev.tech.moex.com/node:22.11.0-bookworm-jq
  variables:
    GIT_STRATEGY: none
  dependencies:
    - build
  script:
    - |
      cd pack-result
      TGZ_FILE=$(ls -t ${PACKAGE_NAME}-*.tgz 2>/dev/null | head -n 1)
      curl -v \
        -H "Authorization: Basic ${DOP_NPM_NEXUS_TOKEN}" \
        -X POST \
        "https://nexus-dev.tech.moex.com/service/rest/v1/components?repository=trade-radar-npm-private-hosted" \
        -F "npm.asset=@./${TGZ_FILE};type=application/octet-stream" \
        --fail
  rules:
    - if: $CI_COMMIT_TAG
      when: manual







/* eslint-disable @typescript-eslint/no-var-requires, import/no-extraneous-dependencies */
const path = require('path');

const autoprefixer = require('autoprefixer');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const removeBeforeAfterBoxSizing = require('./.build/postcss-remove- before-after-box-sizing.cjs');

const base = {
  entry: './src/index.ts',
  resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js'],
    alias: {
      '@src': path.resolve(__dirname, 'src'),
      '@core': path.resolve(__dirname, 'src/core'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@lib': path.resolve(__dirname, 'moex-chart', 'src'),
    },
  },
  module: {
    rules: [
      // Транспиляция TS/JSX через Babel
      {
        test: /\.[jt]sx?$/,
        use: [{ loader: 'babel-loader' }],
        exclude: /node_modules/,
      },
      // CSS
      {
        test: /\.css$/,
        exclude: /\.module\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              importLoaders: 1,
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: { plugins: [removeBeforeAfterBoxSizing(), autoprefixer] },
            },
          },
        ],
      },
      {
        test: /\.scss$/,
        exclude: /\.module\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              modules: false,
              importLoaders: 2,
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [autoprefixer],
              },
            },
          },
          {
            loader: 'sass-loader',
          },
        ],
      },
      {
        test: /\.module\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              modules: { localIdentName: '[name]__[local]__[hash:base64:5]' },
              importLoaders: 1,
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: { plugins: [removeBeforeAfterBoxSizing(), autoprefixer] },
            },
          },
        ],
      },
      {
        test: /\.module\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {
              modules: {
                localIdentName: '[name]__[local]__[hash:base64:5]',
              },
              importLoaders: 2,
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: { plugins: [removeBeforeAfterBoxSizing(), autoprefixer] },
            },
          },
          {
            loader: 'sass-loader',
          },
        ],
      },
    ],
  },
  plugins: [new MiniCssExtractPlugin({ filename: 'styles.css' })],
  optimization: {
    minimize: true,
    minimizer: ['...', new CssMinimizerPlugin()],
    usedExports: true,
    concatenateModules: true,
  },
};

const esm = {
  ...base,
  name: 'esm',
  mode: 'production',
  output: {
    path: path.resolve(process.cwd(), 'dist'),
    filename: 'index.js',
    library: { type: 'module' },
    chunkFormat: 'module',
  },
  experiments: { outputModule: true },
};

const cjs = {
  ...base,
  name: 'cjs',
  mode: 'production',
  output: {
    path: path.resolve(process.cwd(), 'dist'),
    filename: 'index.cjs',
    library: { type: 'commonjs2' },
  },
};

module.exports = [esm, cjs];












/* eslint-disable @typescript-eslint/no-var-requires, import/no-extraneous-dependencies */
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    '@storybook/addon-controls',
    '@storybook/addon-docs',
  ],
  framework: {
    name: '@storybook/react-webpack5',
    options: {},
  },
  core: {
    builder: '@storybook/builder-webpack5',
    disableTelemetry: true,
  },
  webpackFinal: async (config) => {
    config.resolve.extensions = [...(config.resolve.extensions || []), '.js', '.cjs', '.ts', '.tsx'];

    config.resolve.alias = {
      ...config.resolve.alias,
      '@src': path.resolve(__dirname, '../src'),
      '@core': path.resolve(__dirname, '../src/core'),
      '@components': path.resolve(__dirname, '../src/components'),
      '@lib': process.env.buildType === 'local' ? path.resolve(process.cwd(), 'src') : 'moex-chart',
    };

    return {
      ...config,

      module: {
        ...config.module,
        rules: [
          ...config.module.rules,
          {
            test: /\.tsx?$/,
            use: {
              loader: 'ts-loader',
              options: {
                configFile: path.resolve(__dirname, '../tsconfig.json'),
                transpileOnly: true,
              },
            },
            exclude: /node_modules/,
          },
          {
            test: /\.module\.s?css$/,
            use: ['style-loader', 'css-loader', 'sass-loader'],
          },
          {
            test: /\.scss$/,
            exclude: /\.module\.scss$/,
            use: ['style-loader', 'css-loader', 'sass-loader'],
          },
        ],
      },
      plugins: [...config.plugins],
    };
  },
};