My_CICD_Side_2 - itnett/FTD02H-N GitHub Wiki

Ja, det oppsettet du beskriver er en god måte å bruke GitHub Actions for å automatisere og organisere arbeidet ditt på tvers av de ulike repositoriene. La meg oppsummere hvordan dette fungerer og hvorfor det er en optimal tilnærming:

1. Privat CI/CD Pipeline

  • Repository: MyFirst_CICD
  • Type: Privat
  • Formål: Dette repositoriet inneholder dine CI/CD-workflows (GitHub Actions) som automatiserer oppgaver som kodesynkronisering, testing, og distribusjon. Det fungerer som en sentral plass for å administrere og kjøre automatiserte prosesser som oppdaterer dine andre repositorier.

2. Public Legacy Repositories

  • Repositories:
  • Type: Offentlig
  • Formål: Disse repositoriene fungerer som historiske kilder for ditt tidligere arbeid. De inneholder all eksisterende kode og dokumentasjon som du opprinnelig har utviklet. Du bruker CI/CD-pipelinen til å migrere relevant kode og dokumentasjon til de nye repositoriene.

3. Public New Repositories

  • Repositories:
  • Type: Offentlig
  • Formål: Dette er de nye repositoriene hvor du vil fortsette å vedlikeholde og utvikle koden din. Her lagrer du den refaktorerte og oppdaterte koden samt dokumentasjon som du har migrert fra de eldre repositoriene.

Optimal Bruk

  1. Migrering og Organisering

    • Bruk CI/CD-pipelinen i MyFirst_CICD til å automatisere migreringen av kode fra FTD02H-N og FTD02H-N.wiki til FTD02N og FTD02N.wiki.
    • Pipeline kan også automatisk oppdatere dokumentasjonen slik at alle kodeblokker blir migrert til den nye repoen, med lenker som peker til den oppdaterte plasseringen i FTD02N.
  2. Automatisert Testing og Distribusjon

    • Sett opp automatiske tester i CI/CD-pipelinen som kjører hver gang du pushet endringer til FTD02N. Dette sikrer at koden din alltid er stabil og fungerer som forventet.
    • Hvis testene består, kan pipelinen automatisk distribuere oppdateringer til produksjon, eller oppdatere dokumentasjonen.
  3. Versjonskontroll og Historikk

    • Fortsett å bruke FTD02H-N som en arkivkilde, men utfør alt nytt arbeid i FTD02N.
    • Bruk CI/CD til å sikre at det ikke er dupliseringer, og at all ny kode utvikles og vedlikeholdes i det nye repositoriet.
  4. Kontinuerlig Integrasjon og Deploy

    • Konfigurer CI/CD til å automatisk pushe endringer fra MyFirst_CICD til både FTD02N og FTD02N.wiki når endringer gjøres, noe som sikrer at alt er oppdatert og synkronisert på tvers av systemene.
  5. Fleksibel Arbeidsflyt

    • Du kan bruke skriptene du har satt opp til å automatisere vanlige oppgaver som opprettelse av nye mapper, bygging av prosjekter, testing, og distribusjon på tvers av forskjellige miljøer som Trinket, Anaconda, eller lokale systemer.

Eksempel på CI/CD Workflow

Her er et eksempel på hvordan du kan sette opp en GitHub Actions workflow i MyFirst_CICD for å automatisere migrering og oppdatering av dine nye repositorier:

name: Migrate and Update Repositories

on:
  push:
    branches:
      - master

jobs:
  migrate-and-update:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout CI/CD repo
        uses: actions/checkout@v2

      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Run Migration Script
        run: |
          python WikiMigrationScript.py

      - name: Commit and Push Updates to FTD02N
        run: |
          cd ../FTD02N
          git add .
          git commit -m "Automated migration and update from MyFirst_CICD"
          git push
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Update Wiki in FTD02N
        run: |
          cd ../FTD02N.wiki
          git add .
          git commit -m "Automated wiki update from MyFirst_CICD"
          git push
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Fordeler med Dette Oppsettet

  • Automatisering: Du reduserer manuelle trinn og risikoen for feil ved å automatisere oppgaver som migrering, testing, og distribusjon.
  • Tidsbesparelse: CI/CD sikrer at koden din alltid er klar for distribusjon, uten at du trenger å manuelt sjekke eller oppdatere repositoriene dine.
  • Skalerbarhet: Oppsettet gir deg muligheten til å enkelt håndtere et økende volum av kode og dokumentasjon, mens du holder alt organisert og tilgjengelig.
  • Fleksibilitet: Du kan tilpasse pipeline for å møte de spesifikke behovene dine når du jobber med forskjellige verktøy og miljøer.

Dette oppsettet er en robust og skalerbar løsning som vil hjelpe deg med å holde koden din organisert, oppdatert, og i samsvar med beste praksis innen programvareutvikling.

Ja, du kan konfigurere GitHub Actions til å automatisk overvåke endringer i FTD02H-N.wiki og deretter kjøre skriptet for å publisere kode til FTD02N og oppdatere wiki-sidene på FTD02N.wiki. Dette kan gjøres ved å sette opp en workflow i enten FTD02H-N eller MyFirst_CICD som trigges på push til FTD02H-N.wiki.

La meg vise deg hvordan du kan gjøre dette med en GitHub Actions workflow i MyFirst_CICD:

1. Opprett GitHub Actions Workflow

I MyFirst_CICD-repoet, opprett en ny GitHub Actions workflow som overvåker FTD02H-N.wiki.

Opprett eller rediger .github/workflows/ci-cd.yml i MyFirst_CICD med følgende innhold:

name: Migrate and Update Repositories

on:
  push:
    paths:
      - '**.md'
    branches:
      - master

jobs:
  migrate-and-update:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout CI/CD repo
      uses: actions/checkout@v2

    - name: Set up Python
      uses: actions/setup-python@v2
      with:
        python-version: '3.11'

    - name: Clone FTD02H-N.wiki
      run: |
        git clone https://github.com/itnett/FTD02H-N.wiki.git wiki_repo
        cd wiki_repo
        git checkout master

    - name: Run Migration Script
      run: |
        python WikiMigrationScript.py
      env:
        WIKI_REPO_DIR: ${{ github.workspace }}/wiki_repo
        CODE_REPO_URL: https://github.com/itnett/FTD02N.git
        CODE_REPO_DIR: ${{ github.workspace }}/code_repo
        WIKI_OUTPUT_DIR: ${{ github.workspace }}/wiki_output

    - name: Commit and Push Code to FTD02N
      run: |
        cd $CODE_REPO_DIR
        git init
        git remote add origin $CODE_REPO_URL
        git add .
        git commit -m "Automated migration and update from MyFirst_CICD"
        git push -u origin master
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

    - name: Commit and Push Wiki to FTD02N.wiki
      run: |
        cd $WIKI_OUTPUT_DIR
        git init
        git remote add origin https://github.com/itnett/FTD02N.wiki.git
        git add .
        git commit -m "Automated wiki update from MyFirst_CICD"
        git push -u origin master
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

2. Forklaring av Workflow

  • Trigger på push til wiki-repoet: Workflowen trigges når det gjøres endringer i .md-filer i FTD02H-N.wiki, noe som indikerer at innholdet på wiki-sidene er oppdatert.
  • Clone FTD02H-N.wiki: Den kloner wiki-repoet til GitHub Actions-miljøet.
  • Kjør Migreringsskriptet: Dette trinnet kjører skriptet WikiMigrationScript.py, som migrerer koden fra wiki-sidene til FTD02N og oppdaterer wiki-innholdet i FTD02N.wiki.
  • Commit og Push til FTD02N: Workflowen pusher den eksporterte koden til FTD02N.git.
  • Commit og Push til FTD02N.wiki: Workflowen oppdaterer wiki-innholdet i FTD02N.wiki.git med lenker til den nye koden.

3. Opprett Secrets for Autentisering

For at workflowen skal kunne pushe til FTD02N og FTD02N.wiki, må du legge til en GitHub secret kalt GITHUB_TOKEN i repoet MyFirst_CICD. GitHub Actions gir automatisk en token for dette, så du trenger bare å referere til den som vist i koden.

4. Testing og Validering

Når du har konfigurert workflowen, kan du teste den ved å gjøre en endring i FTD02H-N.wiki. Når endringen pushes, vil workflowen automatisk kjøre og migrere koden til FTD02N, samt oppdatere wiki-sidene i FTD02N.wiki.

Alternativ: Direkte i FTD02H-N

Du kan også opprette en lignende workflow direkte i FTD02H-N, slik at workflowen kjører hver gang noen gjør en endring i wiki-sidene. Det kan være en mer direkte tilnærming, men det er opp til deg om du ønsker å holde CI/CD separert i MyFirst_CICD eller integrert i det repoet som påvirkes.

Dette oppsettet gir deg en kraftig og automatisert måte å migrere og oppdatere koden din på tvers av de forskjellige repositoriene uten manuell inngripen, noe som sparer tid og reduserer risikoen for feil.

Jeg skal nå optimalisere WikiMigrationScript.py for CI/CD-integrasjon og sikre at den tar hensyn til alt vi har diskutert. Dette inkluderer å migrere kodeblokker fra FTD02H-N.wiki til FTD02N, oppdatere wiki-innhold med lenker til koden, og gjøre alt dette i en måte som fungerer godt med GitHub Actions for CI/CD.

Her er en optimalisert versjon av WikiMigrationScript.py:

import os
import re
import shutil
import subprocess
import yaml
import logging
import traceback
from datetime import datetime
import stat

# Setup logging
logging.basicConfig(filename="migration.log", level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")

def log(message):
    logging.info(message)
    print(message)

def log_exception(e):
    log(f"Exception occurred: {str(e)}")
    log(traceback.format_exc())

def load_input_config(file_path):
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            config = yaml.safe_load(file)
        validate_config(config)
        log(f"Loaded configuration from {file_path}")
        return config
    except Exception as e:
        log_exception(e)
        raise

def validate_config(config):
    required_keys = ['wiki_repo_url', 'dump_directory', 'code_repo_url', 'code_repo_directory']
    for key in required_keys:
        if key not in config:
            raise ValueError(f"Missing required config key: {key}")
        if not config[key]:
            raise ValueError(f"Config key {key} cannot be empty.")
    log("Configuration validated successfully.")

def handle_remove_readonly(func, path, exc_info):
    excvalue = exc_info[1]
    if func in (os.rmdir, os.remove, os.unlink) and excvalue.errno == errno.EACCES:
        os.chmod(path, stat.S_IWUSR)
        func(path)
    else:
        raise

def run_git_command(commands, cwd):
    result = subprocess.run(commands, cwd=cwd, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    if result.returncode != 0:
        log(f"Git command failed: {' '.join(commands)}")
        log(f"stdout: {result.stdout}")
        log(f"stderr: {result.stderr}")
        raise subprocess.CalledProcessError(result.returncode, commands)
    return result.stdout

def clone_wiki_repo(wiki_repo_url, target_directory):
    try:
        if os.path.exists(target_directory):
            shutil.rmtree(target_directory, onerror=handle_remove_readonly)
        os.makedirs(target_directory)
        run_git_command(["git", "clone", wiki_repo_url, target_directory], cwd=target_directory)
        log(f"Cloned Wiki repository to {target_directory}")
    except Exception as e:
        log_exception(e)
        raise

def process_wiki_files(wiki_dir, code_repo_url, code_repo_dir):
    try:
        for root, dirs, files in os.walk(wiki_dir):
            for file in files:
                if file.endswith(".md"):
                    wiki_filepath = os.path.join(root, file)
                    with open(wiki_filepath, 'r', encoding='utf-8') as f:
                        content = f.read()

                    code_blocks = re.findall(r'```(.*?)\n(.*?)```', content, re.DOTALL)
                    updated_content = content

                    for idx, (lang, code) in enumerate(code_blocks):
                        # Generate a valid filename for the code snippet
                        code_filename = generate_code_filename(file, lang, idx)
                        code_filepath = os.path.join(code_repo_dir, code_filename)

                        # Skip non-executable code
                        if not is_executable_code(lang):
                            continue

                        # Write code to the appropriate file in the repo
                        with open(code_filepath, 'w', encoding='utf-8') as code_file:
                            code_file.write(code.strip())

                        # Replace the code block in the wiki with a link to the code file
                        github_link = f"[{code_filename}]({code_repo_url}/blob/main/{os.path.basename(code_repo_dir)}/{code_filename})"
                        updated_content = updated_content.replace(f"```{lang}\n{code}```", github_link)

                    # Save the updated wiki file with links instead of code
                    with open(wiki_filepath, 'w', encoding='utf-8') as f:
                        f.write(updated_content)

                    log(f"Processed {wiki_filepath} and moved code to {code_repo_dir}")
    except Exception as e:
        log_exception(e)
        raise

def is_executable_code(lang):
    """Determine if the code block is executable or not."""
    return lang in ['python', 'bash', 'sh', 'sql', 'yml', 'makefile', 'powershell']

def generate_code_filename(original_filename, lang, idx):
    """Generate a safe filename for the code snippet."""
    base_name = os.path.splitext(original_filename)[0]
    sanitized_base_name = re.sub(r'\W+', '_', base_name)
    return f"{sanitized_base_name}_snippet_{idx + 1}.{lang}"

def update_changelog(code_repo_dir, log_message):
    try:
        changelog_path = os.path.join(code_repo_dir, "CHANGELOG.md")
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        log_entry = f"{timestamp} - {log_message}\n"

        with open(changelog_path, 'a' if os.path.exists(changelog_path) else 'w', encoding='utf-8') as changelog_file:
            if not os.path.exists(changelog_path):
                changelog_file.write("# CHANGELOG\n\n")
            changelog_file.write(log_entry)

        log(f"Updated CHANGELOG.md with: {log_message}")
    except Exception as e:
        log_exception(e)
        raise

def init_commit_code_repo(code_repo_dir, commit_message):
    try:
        if not os.path.exists(os.path.join(code_repo_dir, ".git")):
            run_git_command(["git", "init"], cwd=code_repo_dir)
            log("Initialized a new git repo.")
        else:
            log("Git repo already initialized.")

        run_git_command(["git", "add", "."], cwd=code_repo_dir)
        run_git_command(["git", "commit", "-m", commit_message], cwd=code_repo_dir)
        log(f"Committed changes with message: {commit_message}")
    except Exception as e:
        log_exception(e)
        raise

def main():
    try:
        config = load_input_config("input.yml")
        wiki_repo_url = config['wiki_repo_url']
        dump_directory = config['dump_directory']
        code_repo_url = config['code_repo_url']
        code_repo_directory = config['code_repo_directory']

        clone_wiki_repo(wiki_repo_url, dump_directory)
        process_wiki_files(dump_directory, code_repo_url, code_repo_directory)
        update_changelog(code_repo_directory, "Moved code from Wiki to code repository.")
        init_commit_code_repo(code_repo_directory, "Initial commit: Imported code from Wiki.")
    except Exception as e:
        log_exception(e)
        raise

if __name__ == "__main__":
    main()

Forklaring av den Optimaliserte Koden

  • Logging: Skriptet bruker logging til å fange opp og logge all aktivitet. Dette er nyttig for feilsøking og å ha en oversikt over hva som har skjedd.
  • Konfigurasjon: input.yml-filen lastes inn og valideres for å sikre at alle nødvendige verdier er til stede.
  • Håndtering av tillatelser: handle_remove_readonly sikrer at skriptet kan slette filer selv om de er skrivebeskyttet.
  • Git-kommandoer: run_git_command kjører alle nødvendige Git-kommandoer, som å klone repoer, committe og pushe endringer.
  • Kodeprosessering: process_wiki_files finner kodeblokker i .md-filer, skiller ut eksekverbar kode (Python, Bash, SQL, etc.), genererer unike filnavn for hver kodeblokk, og erstatter den opprinnelige koden i wiki-filene med lenker til de nye kodefilene i FTD02N.
  • Changelog: update_changelog oppdaterer CHANGELOG.md i kode-repoet for å logge alle endringer som har blitt gjort.
  • Git-Initialisering og Commit: init_commit_code_repo sørger for at alle endringer i kode-repoet blir committet og pushet til GitHub.

Integrering med CI/CD

Denne versjonen av skriptet er godt egnet for å bli brukt i en CI/CD-pipeline, som vi satte opp tidligere. Når workflowen trigges, vil dette skriptet kjøre i GitHub Actions-miljøet, uten behov for lokal kjøring. Det sikrer at alle endringer i FTD02H-N.wiki automatisk migreres og oppdateres i FTD02N og FTD02N.wiki, med riktig logging og changelog-oppdateringer.

Hvordan Bruke Dette Skriptet i CI/CD

  1. Opprett/Rediger Workflow: Sørg for at CI/CD-workflowen du satte opp i MyFirst_CICD repoet, kaller dette skriptet etter at wiki-repoet har blitt klonet.
  2. **Automatisk Migrering

og Oppdatering**: Hver gang det gjøres endringer i wiki-repoet (FTD02H-N.wiki), vil workflowen automatisk kjøre dette skriptet, oppdatere koden og wiki-sidene, og pushe endringene tilbake til FTD02N og FTD02N.wiki. 3. Overvåkning og Feilsøking: Bruk loggingen til å overvåke hva som skjer under migreringen. Hvis noe går galt, vil feilmeldingene bli logget for enkel feilsøking.

Dette oppsettet gir deg en solid basis for å holde koden din ryddig, organisert og automatisk oppdatert, samtidig som du får utnyttet kraften i GitHub Actions for kontinuerlig integrasjon og distribusjon.