Migreren van Azure DevOps naar fremforge
Deze gids beschrijft de migratie van Azure DevOps Services (dev.azure.com) naar fremforge. De migratie vanaf Azure DevOps Server (on-premises) is vergelijkbaar, maar de details van authenticatie en API-endpoints verschillen. Pas de onderdelen hieronder over tokens en endpoints aan voor jouw specifieke installatie.
Van de drie grote migratiebronnen verschilt Azure DevOps qua structuur het meest. ADO heeft aparte producten voor Repos, Pipelines, Boards, Test Plans en Artifacts; fremforge levert Repos + CI/CD + Artifacts + eenvoudige issues als één geïntegreerd geheel en heeft geen tegenhangers voor Test Plans of de volledige functieset van Boards. Een ADO-migratie is daarom deels ook een beslissing over de reikwijdte, naast een technische migratie: voor sommige ADO-functies waarop je misschien leunt, bestaat bij fremforge geen bestemming.
Ontbrekende functies
fremforge heeft geen tegenhangers voor: werkitems van Azure Boards (geen issuehiërarchie of sprintplanning), Test Plans (geen beheer van testgevallen), het automatisch migreren van Azure Artifacts-feeds (pakketten moeten opnieuw worden gepubliceerd) en Classic pipelines (YAML-pipelines migreren wel; designer-pipelines niet). Zijn dit blokkades, bekijk dan de reikwijdte van de migratie voordat je begint.Lees eerst de gids voor migratie vanaf GitHub en de gids voor migratie vanaf GitLab als je dat nog niet hebt gedaan. Een aantal basisstappen (SSH-sleutels, integraties van derden) is identiek en herhalen we hier niet volledig.
Voordat je begint
Wat je zelf nodig hebt:
- De rol Project Administrator op het Azure DevOps-project (of de projecten) dat je migreert.
- Een personal access token op ADO met minimaal de scopes
Code (Read),Code (Status),Work Items (Read),Build (Read),Release (Read)enIdentity (Read). - Beheerderstoegang tot de fremforge-organisatie waarnaar je migreert.
- Voor de migratie van Pipelines: een overzicht van de YAML-pipelinebestanden, eventuele classic (niet-YAML-)pipelines, service connections (die worden OIDC-federatie), variable groups en agent pools waarvan je afhankelijk bent.
Wat we aanraden:
- Zet classic (niet-YAML-)pipelines in ADO om naar YAML-pipelines voordat je migreert. Migreren van classic pipelines naar Forgejo Actions komt neer op alles opnieuw schrijven; eerst naar YAML omzetten geeft je een overdraagbaar startpunt en verbetert ook je ADO-opzet.
- Ga na welke typen werkitems in Boards je echt gebruikt. fremforge (Forgejo) heeft issues en mijlpalen, maar geen Epics, Features, User Stories of Tasks als aparte typen. Die worden allemaal issues met labels. Hangt je werkwijze af van de hiërarchie van werkitemtypen, plan dat samenvoegen dan vóór de migratie.
- Breng afhankelijkheden van Test Plans in kaart. fremforge heeft geen directe tegenhanger; teams die sterk op ADO Test Plans leunen, laten ADO Test Plans meestal als aparte tool doorlopen of stappen over op een speciale tool voor testbeheer.
Geschatte tijd:
- Eén repository met een eenvoudige pipeline en beperkt gebruik van Boards: 1-2 uur.
- Repository met een gemiddeld complexe pipeline en release-pipelines met meerdere stages: 3-6 uur.
- Migratie van een hele organisatie met veel pipelines, variable groups en service connections: 1-2 weken engineering, grotendeels voor het omzetten van pipelines en het vervangen van service connections.
Stap 1: Repository en geschiedenis migreren
De ingebouwde importer van Forgejo ondersteunt Azure DevOps als bron. Hij kopieert de Git-geschiedenis en, afhankelijk van je ADO-configuratie, werkitems (geïmporteerd als issues) en pull requests.
Met de ingebouwde importer (via de UI)
Vanuit de beheer-UI van fremforge:
- Klik op + → Nieuwe migratie.
- Kies Azure DevOps als bron.
- Plak de URL van de repository (bijvoorbeeld
https://dev.azure.com/acme/project/_git/backend). - Plak je personal access token van ADO.
- Vink de soorten inhoud aan die je wilt importeren.
- Kies de doelorganisatie en de naam van de repository.
- Klik op Migreer repository.
Via de API (scriptbaar)
# 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 @-Let op: ADO is geen van de service-waarden die Forgejo voor migraties herkent. De enum op protocolniveau in upstream Forgejo is git, github, gitea, gitlab, gogs, onedev, gitbucket, codebase; git is de terugvaloptie voor gewone Git (sommige oudere documentatie noemt het “plain”, maar de waarde op protocolniveau is letterlijk de string git). "service": "git" expliciet instellen (zoals in de body hierboven) is de canonieke waarde; de ADO-PAT in auth_token zorgt voor de authenticatie, en de clone-URL is een gewone HTTPS-git-remote die de importer voor gewone Git correct afhandelt. Met "lfs": true haalt de importer LFS-objecten op via het LFS-endpoint van de bron; dat is nodig voor ADO-repository’s met LFS-inhoud. Werkitems en PR-metadata importeer je daarna apart met een gescripte workflow op de REST-API van ADO (zie hieronder); de importer voor gewone Git neemt alleen refs mee.
auth_username is verplicht voor ADO. PAT’s van Azure DevOps gebruiken HTTP Basic Auth, waarbij het wachtwoord de PAT is en de gebruikersnaam een willekeurige niet-lege string moet zijn (Microsoft-documentatie: “When using a PAT, the username can be any non-empty string”). Anders bouwt de importer voor gewone Git van Forgejo URL’s in de vorm https://{auth_token}@…, die de Git-server van AzDO als gebruikersnaam leest en met 401 weigert. Gebruik "auth_username": "fremforge" (of een andere niet-lege string; de waarde maakt AzDO niet uit, alleen de vorm van de Basic Auth).
ADO-begrippen in fremforge
| Begrip in Azure DevOps | Begrip in fremforge (Forgejo) |
|---|---|
| Organisation | (geen directe tegenhanger, meestal één fremforge-organisatie per ADO-organisatie) |
| Project | Organisatie, of een voorvoegsel in de namen van repository’s |
| Repository | Repository |
| Pull Request | Pull request |
| Work Item: Epic, Feature, User Story, Task, Bug | Issue met label (epic, feature, story, task, bug) |
| Area Path | Label of eigen mijlpaal |
| Iteration Path | Mijlpaal |
| Build Pipeline | Forgejo Actions-workflow |
| Release Pipeline | Forgejo Actions-workflow met jobs per deploymentomgeving |
| Service Connection | Configuratie voor OIDC-federatie |
| Variable Group | Omgevingssecrets op organisatie- of omgevingsniveau |
| Agent Pool | Runnerlabel / groep eigen runners (BYO) |
| Test Plan / Test Suite | Geen functie van fremforge, externe tool |
| Artifact Feed | Pakketregister van fremforge |
| Wiki | Wiki |
Werkitems → issues
Werkitems worden niet geïmporteerd door de ingebouwde importer van Forgejo. Migratiescript:
#!/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)
}"
donePas het aan waar nodig. Dit is een startpunt, geen kant-en-klare oplossing. Bij grote migraties voeg je backoff bij rate limits en het behouden van opmerkingen toe.
Paginering in WIQL. Azure DevOps begrenst één WIQL-antwoord op 20.000 werkitems. Het script hierboven doet één query en loopt die resultaatset door; voor het gangbare geval is dat prima. Tel eerst voordat je het start:
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}"Ligt COUNT boven ongeveer 19.000, verdeel de query dan (bijvoorbeeld per kwartaal van [System.CreatedDate] of per [System.WorkItemType]) en voer het script per deel uit, of neem voor zeer grote aantallen werkitems contact op met support@frem.sh. De route met één query kapt bij de grens stilzwijgend af: er komt geen foutmelding, alleen een te korte resultaatset, en dat is precies de manier van falen die je tijdens een migratie niet wilt.
Stap 2: Secrets en variabelen
Plekken waar Azure DevOps secrets bewaart:
- Pipelinevariabelen (inline in YAML): herschrijf je tijdens de migratie.
- Variable Groups (op projectniveau, eventueel gekoppeld aan Azure Key Vault): maak je opnieuw aan als secrets op organisatie- of omgevingsniveau in fremforge.
- Geheime variabelen (gemarkeerd als secret, niet teruggegeven door de ADO-API): moet je ophalen uit je leidende secretsopslag en opnieuw invoeren.
- Verwijzingen naar Key Vault: is de variable group gekoppeld aan Azure Key Vault, dan kun je (a) Key Vault houden en de runners van fremforge via OIDC-federatie bij Azure laten authenticeren en de waarden tijdens de job laten ophalen, of (b) de waarden rechtstreeks naar secrets in fremforge kopiëren.
Sterk aangeraden: vervang secrets van Azure-service-principals door OIDC-federatie naar Azure (zie stap 4).
Stap 3: Pipelines omzetten naar Forgejo Actions
YAML voor Azure Pipelines en YAML voor Forgejo Actions lijken qua vorm op elkaar, maar gebruiken een flink andere woordenschat. Het omzetten gaat met de hand. Automatisch omzetten is uitgesteld naar fase 2, afhankelijk van de vraag van klanten.
Omzettingspatronen
Stages en jobs
YAML voor 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'De tegenhanger in 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 testDe belangrijkste omzettingen:
trigger:→on: push:met branchfilters.pr:→on: pull_request:.schedules:→on: schedule:met cron-expressies.stages/jobs/steps→jobs/steps(één niveau platter;stagesheeft geen directe tegenhanger, de volgorde bereik je metneeds:tussen jobs).pool: vmImage: ubuntu-latest→runs-on: fremforge(zie Runner-images voor het besturingssysteem van de runner, de lijst met vooraf geïnstalleerde tools en hoe je toolchains voor talen installeert metsetup-*-actions).script:→run:met hetzelfde shellcommando.task: <name>@<version>→uses: <action-path>@<version>, waarbij de action een gelijkwaardige Marketplace-action is. De meeste ADO-tasks hebben geen directe tegenhanger in Forgejo Actions en worden herschreven alsrun:-stappen of kleine composite actions.
ADO-tasks die vaak omgezet moeten worden
| ADO-task | Vervanging in Forgejo Actions |
|---|---|
UseNode@1 | actions/setup-node@v4 |
UsePythonVersion@0 | actions/setup-python@v5 |
UseDotNet@2 | actions/setup-dotnet@v4 |
UseJavaVersion@1 | actions/setup-java@v4 |
PublishBuildArtifacts@1 | actions/upload-artifact@v4 |
DownloadBuildArtifacts@0 | actions/download-artifact@v4 |
Cache@2 | actions/cache@v4 |
Docker@2 / DockerCompose@0 | docker/build-push-action@v6 of rechtstreeks de docker-CLI in run: |
AzureCLI@2 | azure/cli@v2 met credentials via OIDC-federatie (zie stap 4) |
AzureKeyVault@2 | Secrets van fremforge zelf (voorkeur) of azure/cli@v2 + az keyvault secret show |
SonarCloudPrepare@1 / SonarCloudAnalyze@1 | sonarsource/sonarcloud-github-action@master |
PublishTestResults@2 | dorny/test-reporter@v1 of een artifact-upload op jobniveau + handmatig een rapport genereren |
HelmDeploy@0 | helm/helm-action@v1 of rechtstreeks de helm-CLI |
KubernetesManifest@0 | azure/k8s-deploy@v5 (met OIDC-authenticatie) |
Voorwaarden
condition: in ADO → if: in 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 deployTemplates en Library
Templates in ADO (extends:, template:) komen overeen met herbruikbare workflows in Forgejo Actions (uses: <repo>/.forgejo/workflows/template.yaml@ref) of composite actions (uses: ./.forgejo/actions/<name>). Het omzetten gaat met de hand, maar is mechanisch werk.
Release-pipelines met meerdere stages → deployjobs met een omgevingspoort
Release-pipelines in ADO met goedkeuringspoorten komen overeen met Forgejo Actions-workflows die environment: <name> gebruiken om op omgevingsniveau de flow met verplichte reviewers / goedkeuring te starten. Stel de beveiligingsregels van de omgeving in via de beheer-UI van fremforge op Organisatiebeheer → Omgevingen → <name>.
Agent pools → runnerlabels
pool: vmImage: windows-latest in ADO → runs-on: windows-latest in Forgejo Actions. De gehoste runners van fremforge zijn alleen Linux amd64. Windows en macOS zijn niet beschikbaar in het standaardabonnement.
Hebben je pipelines Windows- of macOS-runners nodig, dan zijn er twee routes:
- Eigen runners (BYO): registreer een Windows- of macOS-runner op je eigen infrastructuur met het label
windows-latestofmacos-latest. Je pipelines sturen ernaar viaruns-on:. - Die pipelines op ADO laten: voor teams die het grootste deel van hun CI migreren, maar Windows/Mac-builds op hun bestaande infrastructuur houden. Niet ideaal, maar als overgangssituatie ondersteund.
Stap 4: Service connections → OIDC-federatie
Azure DevOps gebruikt service connections om cloudcredentials op te slaan. fremforge vervangt die door OIDC-federatie, de voorkeursaanpak voor elk clouddoel, niet alleen Azure.
Voor Azure
- Maak in Azure AD een App Registration aan en stel een federated credential in met:
- Issuer:
https://frem.sh/_app/runner/oidc(één globale issuer voor alle tenants; zie build/runners/oidc/ voor het JWKS-endpoint en de volledige, met GitHub Actions compatibele set claims) - Subject:
repo:<fremforge-org>/<repo>:ref:refs/heads/main(of het patroon voor afbakening dat je verkiest; de subject-claim bevat de organisatie, dus hier wordt de scheiding per tenant afgedwongen) - Audience:
api://AzureADTokenExchange
- Issuer:
- Geef de App Registration de benodigde roltoewijzingen op de Azure-doelabonnement(en).
- In je 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 showGeen client secret. Geen langlevende credential. Het token wordt tijdens de job uitgegeven, is beperkt tot deze workflow en verloopt binnen het uur.
Voor T Cloud Public
Net als bij migraties vanaf GitLab (GitLab, stap 4) ondersteunt fremforge OIDC-federatie naar agencies in T Cloud Public rechtstreeks. Stel dit in via de beheer-UI van fremforge op Instellingen → OIDC Federation.
Voor AWS / GCP
De standaardpatronen voor OIDC naar AWS en OIDC naar GCP werken net zo als vanuit GitHub Actions. Stel de vertrouwensrelatie in met https://frem.sh/_app/runner/oidc als issuer (één globale issuer voor alle tenants; leg in de voorwaarde van het vertrouwensbeleid de claim repository_owner vast voor scheiding per tenant, hetzelfde patroon als het repository_owner-filter van GitHub Actions op token.actions.githubusercontent.com).
Stap 5: SSH-sleutels opnieuw registreren
Zie stap 4 van de GitHub-migratie.
Stap 6: Boards migreren (gedeeltelijk)
Zoals gezegd heeft fremforge geen hiërarchie van werkitemtypen. Migratieopties:
- Platslaan: alle werkitems → issues met typelabels. Query’s en rapporten bouw je opnieuw op rond de zoekfunctie van fremforge.
- Boards apart houden: exporteer de ADO-werkitems naar een plat gegevensbestand, archiveer dat en blijf ADO Boards gebruiken voor backlogbeheer, terwijl je alleen code en CI migreert. Dat is een gangbare tussenoplossing voor teams die Boards intensief gebruiken.
- Vervangen door een speciale tool voor projectbeheer: Linear, Jira, Shortcut, GitHub Projects (als je in het GitHub-ecosysteem blijft maar ADO verlaat). De webhooks en REST-API van fremforge integreren met al deze tools.
Het importscript in stap 1 verzorgt optie 1 met platslaan op basis van labels.
Stap 7: Artifact-feeds → pakketregister van fremforge
Artifact-feeds van ADO komen overeen met het pakketregister van fremforge. Ondersteunde formaten op fremforge:
- npm
- Maven
- Docker/OCI-containers
- NuGet
- PyPI
- RubyGems
- Composer
- Go-modules
- Generic
Migreren werkt via pushen: elke publicerende pipeline publiceert na de migratie de artifacts opnieuw naar het register van fremforge. Historische versies van artifacts op ADO blijven daar beschikbaar. Faseer ze uit in je eigen tempo.
Stap 8: Integraties van derden opnieuw koppelen
Zie stap 5 van de GitHub-migratie. ADO-specifieke integraties (Teams Service Hooks, ServiceNow, ADO-specifieke webhooks) koppel je opnieuw als webhooks van fremforge.
Stap 9: Verifiëren en uitfaseren
Hetzelfde als in de gids voor GitHub.
Veelvoorkomende valkuilen bij ADO-migraties
Classic pipelines kunnen niet automatisch worden gemigreerd.
Heb je classic (niet-YAML-)pipelines, zet ze dan eerst in ADO om naar YAML. Pas daarna de omzettingspatronen uit stap 3 toe. Sla je de tussenstap via YAML over, dan moet je pipelines opnieuw opbouwen vanuit de logische opzet in de ADO-UI, en dat is foutgevoelig.
Service connections met verwijzingen naar Azure Key Vault.
Een service connection die tijdens de uitvoering van de pipeline uit Azure Key Vault leest, vraagt om een migratie in twee stappen: (1) richt OIDC-federatie in zodat de runner van fremforge az login kan doen; (2) de workflow haalt het secret daarna tijdens de job op met az keyvault secret show, in plaats van het in secrets van fremforge op te nemen. Dat volgt het ADO-patroon precies.
Release-pipelines met goedkeuringspoorten.
Release-pipelines in ADO met handmatige goedkeuringspoorten vóór een productiedeploy komen overeen met Forgejo Actions met beveiligingsregels voor environment:. In de beheer-UI van fremforge stel je per omgeving verplichte reviewers in. De functionaliteit is gelijkwaardig; alleen de gebruikerservaring verschilt.
Afhankelijkheid van Test Plans.
Handmatige testuitvoering die in ADO Test Plans wordt bijgehouden, heeft bij fremforge geen bestemming. Teams die daarop leunen, moeten een vervangende tool kiezen (Xray voor Jira, Zephyr, qTest) of de kleinere reikwijdte accepteren.
Hulp krijgen
support@frem.sh met onderwerpregel MIGRATION, AZURE DEVOPS, <your-specific-issue>.
Zie ook: Gids voor migratie vanaf GitHub · Gids voor migratie vanaf GitLab · Compatibiliteitsmatrix van de top 20 Marketplace-actions · Checklist voor de migratie.