q-shift / backstage-playground

2 stars 6 forks source link

Use featureFlags to switch between gitea or github #161

Open cmoulliard opened 1 week ago

cmoulliard commented 1 week ago

TODO

The featureFlag should be used, part of our templates to by example switch between gitea or github as described hereafter for demo, testing purposes

  1. Patch the creatApp() ts file with some featureFlags:
    const app = createApp({
    apis,
    featureFlags: [
      {
          name: 'scaffold-template-gitea',
          description: 'Enable gitea provider field instead of github',
          pluginId: '',
      },
  2. Open the page http://localhost:3000/settings/feature-flags to enable the needed feature
  3. Customize the template
    parameters:
      - name: Git Repository
        description: Git Repository
        properties:
         gitea:
           title: Gitea Repo
           type: string
           description: Gitea Repo Url
           backstage:featureFlag: scaffold-template-gitea
         github:
           title: Github Repo
           type: string
           description: Github Repo Url
           backstage:featureFlag: scaffold-template-github
  4. Add the logic part of the step to consume the proper git provider

    - id: publish-github
      name: Publishing to a github repository
      action: debug:log
      if: ${{ parameters.github }}
      input:
        message: |
          Pushing files to ${{ parameters.github }} repository
    
    - id: publish-gitea
      name: Publishing to a gitea repository
      action: debug:log
      if: ${{ parameters.gitea }}
      input:
        message: |
          Pushing files to ${{ parameters.gitea }} repository
cmoulliard commented 1 week ago

There is nevertheless a limitation as the featureFlags are stored within the browser's local storage and I don't think that we could set them when running backstage part of the github workflow as the js code runs within the browser and is accessed by the user when they click within the user's setting screen on the feature(s) to be enabled/disabled

A solution could be to use a headless browser to simulate what the user do as documented here: https://scrapfly.io/blog/what-is-local-storage-and-how-to-scrape-it/ and to enable the checkbox of the corresponding <input/> html element

Screenshot 2024-06-17 at 16 55 06

cmoulliard commented 1 week ago

I did a test using puppeteer - which allows to open pages, navigate and set objects within the localstorage

Remark: Playwright could also be used instead of puppeteer: https://blog.logrocket.com/playwright-vs-puppeteer/

import puppeteer from 'puppeteer'; // or import puppeteer from 'puppeteer-core';

const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('http://localhost:3000')

// Don't work as cannot find
// await page.click('text=ENTER');

await page.keyboard.press('Tab');  // navigate to button
await page.keyboard.type('\n');  // hit enter

await page.goto('http://localhost:3000/settings/feature-flags');

let localStorageData = await page.evaluate(() => JSON.parse(JSON.stringify(localStorage)));

await page.evaluate(() => {
    localStorage.setItem('language', 'fr');
});

await page.evaluate(() => {
    localStorage.setItem('featureFlags', '{"scaffold-template-gitea":1}');
});

localStorageData = await page.evaluate(() => JSON.parse(JSON.stringify(localStorage)));
console.log(localStorageData);

await browser.close();
cmoulliard commented 1 week ago

There is nevertheless a limitation as the featureFlags are stored within the browser's local storage and I don't think that we could set them when running backstage part of the github workflow as the js code runs within the browser and is accessed by the user when they click within the user's setting screen on the feature(s) to be enabled/disabled

Such a limitation is not a problem for github workflow as we don't have to access the front UI and we can set the parameters of the scaffold template hidden or not to curl a http POST ;-)

cmoulliard commented 1 week ago

An alternative where featureFlags is not needed is to declare the different Git providers using a more manual approach vs getting them using the repoUrlPicker:

    - title: Configure the Git repository
      required:
        - repo
      properties:
        repo:
          title: Repository Location
          type: object
          properties:
            host:
              title: Repo Host
              type: string
              default: gitea.cnoe.localtest.me:8443
              enum:
                - gitea.cnoe.localtest.me:8443
                - github.com
                -
            org:
              title: Repo Org Owner
              type: string
              description: Your SCM organization/group
              default: qshift
              enum:
                - qshift
                - ch007m
                - iocanel
                - aureamunoz
                - tqvarnst

            visibility:
              title: Visibility of the repository
              type: string
              default: 'public'
              enum:
                - 'public'
                - 'private'
              enumNames:
                - 'public'
                - 'private'

and to process them as such:

    - id: publish
      name: Publishing to Code Source Repository - Github
      action: publish:github
      if: ${{ parameters.repo.host === "github.com" }}
      input:
        allowedHosts: ['github.com']
        description: This is ${{ parameters.component_id }}
        repoUrl: "${{ parameters.repo.host }}?owner=${{ parameters.repo.org }}&repo=${{parameters.component_id}}"
        defaultBranch: main
        protectDefaultBranch: false
        repoVisibility: ${{ parameters.repo.visibility }}

    - id: publish
      name: Publishing to a gitea git repository
      action: publish:gitea
      if: ${{ parameters.repo.host !== "github.com" }}
      input:
        name: This is a dummy project
        description: This is ${{ parameters.component_id }}
        repoUrl: ${{ parameters.repo.host }}?owner=${{ parameters.repo.org }}&repo=${{ parameters.component_id }}
        repoVisibility: ${{ parameters.repo.visibility }}
        defaultBranch: main

WDYT ? @iocanel @aureamunoz