Gå til hovedindhold

Migrer til fremforge fra Azure DevOps

Denne vejledning dækker migrering fra Azure DevOps Services (dev.azure.com) til fremforge. Migrering fra Azure DevOps Server (on-premises) ligner, men detaljerne om godkendelse og API-endpoints er anderledes. Tilpas token- og endpointdelene nedenfor til din konkrete installation.

Azure DevOps er den af de tre store kildeplatforme, der adskiller sig mest strukturelt. ADO har separate produkter til Repos, Pipelines, Boards, Test Plans og Artifacts; fremforge leverer Repos + CI/CD + Artifacts + basale issues som én samlet overflade og har ingen modsvarighed til Test Plans eller hele Boards’ funktionssæt. En ADO-migrering er derfor lige så meget en beslutning om omfang som en teknisk migrering: nogle ADO-funktioner, du måske er afhængig af, har ingen plads at lande i fremforge.

Manglende funktioner

fremforge har ingen modsvarighed til: work items i Azure Boards (intet issue-hierarki og ingen sprintplanlægning), Test Plans (ingen håndtering af testcases), automatisk migrering af Azure Artifacts-feeds (pakker skal udgives igen) og klassiske pipelines (YAML-pipelines kan migreres, pipelines fra designeren kan ikke). Hvis noget af dette er en blokering, så vurder migreringens omfang, før du går i gang.

Læs vejledningen til migrering fra GitHub og vejledningen til migrering fra GitLab først, hvis du ikke allerede har gjort det. Nogle grundlæggende trin (SSH-nøgler, tredjepartsintegrationer) er de samme, og dem gentager vi ikke i fuld længde her.

Før du starter

Det skal du have på din side:

  • Rollen Project Administrator i de Azure DevOps-projekter, du migrerer.
  • Et personligt adgangstoken i ADO med mindst scopes Code (Read), Code (Status), Work Items (Read), Build (Read), Release (Read) og Identity (Read).
  • Administratoradgang til den fremforge-organisation, du migrerer til.
  • Til migrering af Pipelines: en oversigt over YAML-pipelinefiler, eventuelle klassiske pipelines (uden YAML), service connections (de bliver til OIDC-føderation), variable groups og de agent pools, du afhænger af.

Det anbefaler vi:

  • Konvertér alle klassiske pipelines (uden YAML) til YAML-pipelines i ADO, før du migrerer. En migrering fra klassiske pipelines til Forgejo Actions er i praksis en omskrivning fra bunden; konverterer du til YAML først, får du et flytbart udgangspunkt og samtidig en bedre ADO-opsætning.
  • Find ud af, hvilke typer work items i Boards du reelt bruger. fremforge (Forgejo) har issues og milepæle, men har ikke Epics, Features, User Stories eller Tasks som separate typer. De bliver alle til issues med labels. Hvis din proces afhænger af hierarkiet mellem typer af work items, så planlæg sammenlægningen før migreringen.
  • Find afhængigheder af Test Plans. fremforge har ingen direkte modsvarighed; teams, der er meget afhængige af ADO Test Plans, beholder typisk ADO Test Plans som et separat værktøj eller flytter til et dedikeret værktøj til testhåndtering.

Tidsestimat:

  • Ét repository med en enkel pipeline og lidt brug af Boards: 1-2 timer.
  • Et repository med moderat kompleks pipeline og release-pipelines i flere stages: 3-6 timer.
  • Migrering af en hel organisation med mange pipelines, variable groups og service connections: 1-2 udviklerugers arbejde, hvor konvertering af pipelines og udskiftning af service connections fylder mest.

Trin 1: Migrering af repositories og historik

Forgejos indbyggede importør understøtter Azure DevOps som kilde. Den kopierer Git-historikken og, afhængigt af din ADO-konfiguration, work items (importeret som issues) og pull requests.

Med den indbyggede importør (via brugerfladen)

Fra fremforges administration:

  1. Klik på + → Ny migration.
  2. Vælg Azure DevOps som kilde.
  3. Indsæt repositoryets URL (f.eks. https://dev.azure.com/acme/project/_git/backend).
  4. Indsæt dit personlige adgangstoken fra ADO.
  5. Sæt flueben ved det indhold, der skal importeres.
  6. Vælg målorganisationen og navnet på repositoryet.
  7. Klik på Migrate repository.

Med API’et (til scripts)

# Build the JSON body via jq so the PAT is JSON-string-escaped safely
# (Azure DevOps PATs can contain `/`, `+`, `=` characters which are
# fine in JSON strings but a raw shell-interpolation can still break
# if the PAT happens to contain `"` from a copy-paste error).
jq -nc \
  --arg clone_addr    "https://dev.azure.com/acme/project/_git/backend" \
  --arg auth_username "fremforge" \
  --arg auth_token    "$ADO_TOKEN" \
  --arg repo_owner    "acme" \
  --arg repo_name     "backend" \
  '{clone_addr: $clone_addr, auth_username: $auth_username, auth_token: $auth_token,
    service: "git", repo_owner: $repo_owner, repo_name: $repo_name,
    issues: false, pull_requests: false, lfs: true}' \
| curl -X POST "https://frem.sh/api/v1/repos/migrate" \
    -H "Authorization: Bearer ${FREMFORGE_TOKEN}" \
    -H "Content-Type: application/json" \
    -d @-

Bemærk: ADO er ikke en af de service-værdier til migrering, som Forgejo kender. Upstream Forgejos enum på protokolniveau er git, github, gitea, gitlab, gogs, onedev, gitbucket, codebase, hvor git er reserveløsningen for ren Git (noget ældre dokumentation kalder den “plain”, men værdien er den bogstavelige streng git). Det er den kanoniske værdi at sætte "service": "git" eksplicit (som i body’en ovenfor); ADO-PAT’en i auth_token står for godkendelsen, og clone-URL’en er et almindeligt HTTPS-Git-remote, som importøren til ren Git håndterer korrekt. "lfs": true får importøren til at hente LFS-objekter gennem kildens LFS-endpoint, hvilket er nødvendigt for ADO-repos med LFS-indhold. Work items og PR-metadata importeres derefter separat med et script, der bruger ADO’s REST API (se nedenfor); importøren til ren Git henter kun refs.

auth_username er påkrævet for ADO. PAT’er i Azure DevOps bruger HTTP Basic Auth, hvor adgangskoden er PAT’en, og brugernavnet skal være en vilkårlig streng, der ikke er tom (Microsofts dokumentation: “When using a PAT, the username can be any non-empty string”). Ellers bygger Forgejos importør til ren Git URL’er i stil med https://{auth_token}@…, som AzDO’s Git-server opfatter som brugernavnet og afviser med 401. Brug "auth_username": "fremforge" (eller en anden streng, der ikke er tom; værdien er ligegyldig for AzDO, det er kun formen på basic auth, der tæller).

Sådan svarer ADO’s begreber til fremforges

Begreb i Azure DevOpsBegreb i fremforge (Forgejo)
Organisation(ingen direkte modsvarighed; typisk én fremforge-organisation pr. ADO-organisation)
ProjectOrganisation eller et præfiksmønster i repositorynavne
RepositoryRepository
Pull RequestPull request
Work Item: Epic, Feature, User Story, Task, BugIssue med label (epic, feature, story, task, bug)
Area PathLabel eller egen milepæl
Iteration PathMilepæl
Build PipelineForgejo Actions-workflow
Release PipelineForgejo Actions-workflow med jobs til udrulningsmiljøer
Service ConnectionKonfiguration af OIDC-føderation
Variable GroupSecrets på organisations- eller miljøniveau
Agent PoolRunner-label / gruppe af egne runnere
Test Plan / Test SuiteIkke en funktion i fremforge; eksternt værktøj
Artifact Feedfremforges pakke-registry
WikiWiki

Work items → issues

Work items importeres ikke med Forgejos indbyggede importør. Script til migrering:

#!/bin/bash
# Requires: curl, jq, ADO_TOKEN, FREMFORGE_TOKEN
ADO_ORG="acme"
ADO_PROJECT="project"
FREMFORGE_ORG="acme"
FREMFORGE_REPO="backend"

# Query all work items in the project
curl -s -u ":${ADO_TOKEN}" \
  "https://dev.azure.com/${ADO_ORG}/${ADO_PROJECT}/_apis/wit/wiql?api-version=7.1" \
  -H "Content-Type: application/json" \
  -d '{"query":"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject]=@project"}' \
  | jq -r '.workItems[].id' \
  | while read wi_id; do
    # Fetch full work item
    ado_wi=$(curl -s -u ":${ADO_TOKEN}" \
      "https://dev.azure.com/${ADO_ORG}/_apis/wit/workitems/${wi_id}?api-version=7.1")

    title=$(echo "${ado_wi}" | jq -r '.fields."System.Title"')
    body=$(echo "${ado_wi}" | jq -r '.fields."System.Description" // ""')
    wi_type=$(echo "${ado_wi}" | jq -r '.fields."System.WorkItemType"' | tr '[:upper:]' '[:lower:]')
    state=$(echo "${ado_wi}" | jq -r '.fields."System.State"')

    # Create fremforge issue
    curl -s -X POST "https://frem.sh/api/v1/repos/${FREMFORGE_ORG}/${FREMFORGE_REPO}/issues" \
      -H "Authorization: Bearer ${FREMFORGE_TOKEN}" \
      -H "Content-Type: application/json" \
      -d "{
        \"title\": \"${title}\",
        \"body\": \"**Migrated from Azure DevOps work item #${wi_id}**\n\n${body}\",
        \"labels\": [\"${wi_type}\"],
        \"closed\": $([[ "${state}" == "Closed" || "${state}" == "Done" || "${state}" == "Resolved" ]] && echo true || echo false)
      }"
  done

Tilpas det efter behov. Det er et udgangspunkt, ikke en færdig løsning. Store migreringer bør tilføje backoff ved rate limits og bevarelse af kommentarer.

Sideinddeling i WIQL. Azure DevOps begrænser ét WIQL-svar til 20.000 work items. Scriptet ovenfor sender én forespørgsel og gennemløber det resultat, hvilket er fint i det almindelige tilfælde. Tæl først, før du sætter det i gang:

COUNT=$(curl -s -u ":${ADO_TOKEN}" \
  "https://dev.azure.com/${ADO_ORG}/${ADO_PROJECT}/_apis/wit/wiql?api-version=7.1" \
  -H "Content-Type: application/json" \
  -d '{"query":"SELECT [System.Id] FROM WorkItems WHERE [System.TeamProject]=@project"}' \
  | jq '.workItems | length')
echo "Work items in scope: ${COUNT}"

Hvis COUNT er over ca. 19.000, så del forespørgslen op (f.eks. pr. kvartal af [System.CreatedDate] eller pr. [System.WorkItemType]), og kør scriptet én gang pr. del, eller kontakt support@frem.sh ved meget store mængder work items. Med én forespørgsel bliver resultatet afkortet i stilhed ved grænsen: der kommer intet fejlsvar, bare et kortere resultat, og det er netop den fejl, du ikke vil have under en migrering.

Trin 2: Secrets og variabler

Steder, hvor Azure DevOps gemmer secrets:

  • Pipeline-variabler (direkte i YAML): skrives om under migreringen.
  • Variable Groups (på projektniveau, eventuelt koblet til Azure Key Vault): oprettes igen som secrets på organisations- eller miljøniveau i fremforge.
  • Secret-variabler (markeret som secret, returneres ikke af ADO’s API): skal hentes fra det system, hvor dine secrets officielt ligger, og indtastes igen.
  • Referencer til Key Vault: hvis en variable group er koblet til Azure Key Vault, er strategien enten (a) at beholde Key Vault og lade fremforges runnere godkende sig mod Azure via OIDC-føderation og hente værdierne, når jobbet kører, eller (b) at kopiere værdierne direkte over i fremforge-secrets.

Vi anbefaler kraftigt at erstatte secrets til Azure service principals med OIDC-føderation til Azure (se trin 4).

Trin 3: Konvertering fra Pipelines til Forgejo Actions

YAML i Azure Pipelines og YAML i Forgejo Actions ligner hinanden i formen, men bruger et væsentligt anderledes ordforråd. Konverteringen sker i hånden. Automatisk konvertering er udskudt til fase 2, hvis kunderne efterspørger den.

Mønstre til konvertering

Stages og jobs

YAML i Azure Pipelines:

trigger: [main]

stages:
  - stage: Build
    jobs:
      - job: BuildApp
        pool:
          vmImage: ubuntu-latest
        steps:
          - script: make build
            displayName: 'Build'

  - stage: Test
    dependsOn: Build
    jobs:
      - job: TestApp
        pool:
          vmImage: ubuntu-latest
        steps:
          - script: make test
            displayName: 'Test'

Det tilsvarende i Forgejo Actions:

name: CI

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: fremforge
    steps:
      - uses: actions/checkout@v4
      - name: Build
        run: make build

  test:
    needs: build
    runs-on: fremforge
    steps:
      - uses: actions/checkout@v4
      - name: Test
        run: make test

De vigtigste konverteringer:

  • trigger: → on: push: med branch-filtre.
  • pr: → on: pull_request:.
  • schedules: → on: schedule: med cron-udtryk.
  • stages / jobs / steps → jobs / steps (ét niveau fladere; stages har ingen direkte modsvarighed, og rækkefølgen opnås med needs: mellem jobs).
  • pool: vmImage: ubuntu-latest → runs-on: fremforge (se Runner-images for runnerens OS, listen over forudinstallerede værktøjer, og hvordan du installerer sprogværktøjer med setup-*-actions).
  • script: → run: med samme shellkommando.
  • task: <name>@<version> → uses: <action-path>@<version>, hvor action’en er en tilsvarende Marketplace-action. De fleste ADO-tasks har ingen direkte modsvarighed i Forgejo Actions og skrives om til run:-steps eller små composite actions.

ADO-tasks, der ofte skal konverteres

ADO-taskErstatning i Forgejo Actions
UseNode@1actions/setup-node@v4
UsePythonVersion@0actions/setup-python@v5
UseDotNet@2actions/setup-dotnet@v4
UseJavaVersion@1actions/setup-java@v4
PublishBuildArtifacts@1actions/upload-artifact@v4
DownloadBuildArtifacts@0actions/download-artifact@v4
Cache@2actions/cache@v4
Docker@2 / DockerCompose@0docker/build-push-action@v6 eller docker-CLI direkte i run:
AzureCLI@2azure/cli@v2 med legitimationsoplysninger fra OIDC-føderation (se trin 4)
AzureKeyVault@2fremforges egne secrets (foretrukket) eller azure/cli@v2 + az keyvault secret show
SonarCloudPrepare@1 / SonarCloudAnalyze@1sonarsource/sonarcloud-github-action@master
PublishTestResults@2dorny/test-reporter@v1 eller upload af artefakt på jobniveau + manuel generering af rapport
HelmDeploy@0helm/helm-action@v1 eller helm-CLI direkte
KubernetesManifest@0azure/k8s-deploy@v5 (godkendt med OIDC)

Betingelser

condition: i ADO → if: i Forgejo Actions.

ADO:

- task: Deploy
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))

Forgejo Actions:

- name: Deploy
  if: success() && github.ref == 'refs/heads/main'
  run: make deploy

Skabeloner og Library

ADO-skabeloner (extends:, template:) svarer til genbrugelige workflows i Forgejo Actions (uses: <repo>/.forgejo/workflows/template.yaml@ref) eller composite actions (uses: ./.forgejo/actions/<name>). Konverteringen sker i hånden, men er mekanisk.

Release-pipelines i flere stages → udrulningsjobs bag miljøer

ADO-release-pipelines med godkendelser svarer til Forgejo Actions-workflows, der bruger environment: <name> til at udløse godkendelsen med krævede reviewere på miljøniveau. Sæt beskyttelsesreglerne for miljøet op i fremforges administration under Administration → Miljøer → <name>.

Agent pools → runner-labels

pool: vmImage: windows-latest i ADO → runs-on: windows-latest i Forgejo Actions. De hostede runnere, som fremforge stiller til rådighed, er kun Linux amd64. Windows og macOS findes ikke på standardplanen.

Hvis dine pipelines kræver Windows- eller macOS-runnere, er der to veje:

  1. Egne runnere: registrer en Windows- eller macOS-runner på din egen infrastruktur med labelen windows-latest eller macos-latest. Dine pipelines rammer dem via runs-on:.
  2. Behold de pipelines i ADO: for teams, der flytter det meste af deres CI, men beholder Windows/Mac-builds på eksisterende infrastruktur. Ikke ideelt, men understøttet som en overgangsløsning.

Trin 4: Service connections → OIDC-føderation

Azure DevOps bruger service connections til at gemme legitimationsoplysninger til clouds. fremforge erstatter dem med OIDC-føderation, som er den foretrukne løsning for alle cloud-mål, ikke kun Azure.

Til Azure

  1. Opret en App Registration i Azure AD, og konfigurer en federated credential med:
    • Issuer: https://frem.sh/_app/runner/oidc (én global udsteder for alle tenants; se build/runners/oidc/ for JWKS-endpointet og det fulde sæt claims, der er kompatibelt med GitHub Actions)
    • Subject: repo:<fremforge-org>/<repo>:ref:refs/heads/main (eller det scope-mønster, du foretrækker; subject-claimet indeholder organisationen, så isolationen pr. tenant håndhæves her)
    • Audience: api://AzureADTokenExchange
  2. Giv din App Registration de nødvendige rolletildelinger på mål-subscriptionen eller -subscriptionerne i Azure.
  3. I dit Forgejo Actions-workflow:
permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: fremforge
    steps:
      - uses: azure/login@v2
        with:
          client-id: ${{ vars.AZURE_CLIENT_ID }}
          tenant-id: ${{ vars.AZURE_TENANT_ID }}
          subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}
      - run: az account show

Ingen client secret. Ingen langtidsholdbar legitimation. Tokenet udstedes, når jobbet kører, har scope til dette workflow og udløber inden for en time.

Til T Cloud Public

Som ved GitLab-migreringer (GitLab trin 4) understøtter fremforge OIDC-føderation direkte til T Cloud Public-agencies. Sæt det op i fremforges administration under Indstillinger → OIDC Federation.

Til AWS / GCP

De almindelige mønstre for OIDC til AWS og OIDC til GCP virker på samme måde som fra GitHub Actions. Sæt tillidsforholdet op med https://frem.sh/_app/runner/oidc som udsteder (én global udsteder for alle tenants; lås betingelsen i tillidspolitikken til claimet repository_owner for at få isolation pr. tenant, samme mønster som GitHub Actions’ repository_owner-filter på token.actions.githubusercontent.com).

Trin 5: Ny registrering af SSH-nøgler

Se trin 4 i GitHub-migreringen.

Trin 6: Migrering af Boards (delvis)

Som nævnt har fremforge intet hierarki af work item-typer. Muligheder for migreringen:

  1. Gør det fladt: alle work items → issues med type-labels. Forespørgsler og rapporter bygges op igen omkring fremforges søgning.
  2. Behold Boards separat: eksportér ADO’s work items til en flad datafil, arkivér den, og fortsæt med at bruge ADO Boards til backlog-styring, mens du kun migrerer kode og CI. Det er en almindelig mellemtilstand for teams, der bruger Boards avanceret.
  3. Erstat med et dedikeret projektstyringsværktøj: Linear, Jira, Shortcut, GitHub Projects (hvis du bliver i GitHubs økosystem, men forlader ADO). fremforges webhooks og REST API integrerer med dem alle.

Importscriptet i trin 1 klarer mulighed 1 med udfladning baseret på labels.

Trin 7: Artifact feeds → fremforges pakke-registry

ADO’s Artifact feeds svarer til fremforges pakke-registry. Formater, som fremforge understøtter:

  • npm
  • Maven
  • Docker/OCI-containere
  • NuGet
  • PyPI
  • RubyGems
  • Composer
  • Go-moduler
  • Generic

Migreringen sker ved push: hver pipeline, der udgiver, udgiver artefakterne igen til fremforges registry efter migreringen. Tidligere versioner af artefakter i ADO forbliver tilgængelige der. Luk ned i dit eget tempo.

Trin 8: Genforbindelse af tredjepartsintegrationer

Se trin 5 i GitHub-migreringen. ADO-specifikke integrationer (Teams Service Hooks, ServiceNow, ADO-specifikke webhooks) forbindes igen som fremforge-webhooks.

Trin 9: Verificer, og luk ned

Som i GitHub-vejledningen.

Almindelige faldgruber ved ADO-migreringer

Klassiske pipelines kan ikke migreres automatisk.

Har du klassiske pipelines (uden YAML), så konvertér dem til YAML i ADO først. Brug derefter konverteringsmønstrene i trin 3. Springer du mellemtrinnet med YAML over, skal pipelines genskabes ud fra den logiske struktur i ADO’s brugerflade, og det giver let fejl.

Service connections med referencer til Azure Key Vault.

En service connection, der læser fra Azure Key Vault, mens pipelinen kører, kræver en migrering i to trin: (1) sæt OIDC-føderation op, så fremforges runner kan køre az login; (2) workflowet henter så secreten med az keyvault secret show, når jobbet kører, i stedet for at lægge den i fremforge-secrets. Det svarer nøjagtigt til mønsteret i ADO.

Release-pipelines med godkendelser.

ADO-release-pipelines med manuel godkendelse før udrulning til produktion svarer til Forgejo Actions med beskyttelsesregler på environment:. I fremforges administration kan du sætte krævede reviewere op pr. miljø. Funktionerne er de samme; kun brugeroplevelsen er anderledes.

Afhængighed af Test Plans.

Manuel testudførelse, der følges i ADO Test Plans, har ingen plads at lande i fremforge. Teams, der er afhængige af det, skal vælge et andet værktøj (Xray til Jira, Zephyr, qTest) eller acceptere det mindre omfang.

Få hjælp

support@frem.sh med emnelinjen MIGRATION, AZURE DEVOPS, <your-specific-issue>.


Se også: Vejledning til migrering fra GitHub · Vejledning til migrering fra GitLab · Kompatibilitetsmatrix for de 20 mest brugte Marketplace-actions · Tjekliste før migrering.