Files
gitea-ci-library/skills/gitops-update/SKILL.md
T
niko bc6bb78973
CI Git-Pages Main / Load git-pages.gitea-env.conf to pipeline env (push) Successful in 34s
CI Main / Check existing artifact (push) Successful in 22s
CI Git-Pages Main / Build & Push Helm chart (push) Successful in 48s
CI Main / Bats tests (push) Successful in 1m34s
acc-tests Cucumber test report
CI Main / Cucumber tests (push) Successful in 1m45s
CI Main / Load example-gitea-env.conf to pipeline env (push) Successful in 34s
CI Git-Pages Main / Check existing artifact (push) Successful in 21s
ci-helm-build-push Helm push 0.1.5
unit-tests Bats test report
CI Git-Pages Main / Update chart to the cluster (push) Failing after 0s
ci-docker-build-push Docker push 0.2.25
CI Git-Pages Main / Report Summary (push) Successful in 7s
CI Main / Build & Push Docker (push) Successful in 44s
CI Main / GitOps (push) Failing after 22s
CI Main / Move provider version tag (push) Has been skipped
CI Main / Report Summary (push) Successful in 6s
Feature/gitops (#37)
Co-authored-by: moilanik <niko.moilanen@tietoevry.com>
Reviewed-on: #37
2026-06-22 10:37:15 +03:00

15 KiB

name, description, activation-gate, category, impact
name description activation-gate category impact
gitops-update Setting up GitOps version updates: GitOps-repo workflow template, code repo dispatch, secret requirements, and two-repo commit-status pattern. Activates when the user needs to wire up artifact builds to GitOps configuration updates. User mentions GitOps update, gitops-update, dispatch to another repo, two-repo version bump, cross-repo deployment, or wiring build output to config repo. ci high

GitOps Update — Provider-palvelu

scripts/gitops-update.sh ja scripts/dispatch-workflow.sh muodostavat GitOps-päivityspalvelun. Artifact buildataan code repossa, minkä jälkeen code repo dispatchaa GitOps-repoon, joka päivittää konfiguraatiotiedoston ja pushaa muutoksen.

Arkkitehtuuri

Kaksi erillistä repoa, eristetyt oikeudet:

Code repo                          GitOps repo
(build & push artifact)            (konfiguraatiot)

build & push onnistuu (v0.2.3)
         │
         │ dispatch ci-main.yml
         │ {file, yq_tpl, version, source_repo, source_commit}
         │
         └────────────────────────────────────→┐
                                               │
         dispatch-workflow.sh pollaa ←─────────┘
                                               │
         code repo asettaa                     │ git clone, yq update,
         oman commit-statusnsa                 │ git commit + push
         dispatchin exit-koodilla              │ status GitOps-repoon

Token-periaate: Vain GitOps-repoon kirjoitetaan. Code repo asettaa oman commit-statusnsa dispatch-kutsun exit-koodin perusteella omalla auto-tokenillaan. GitOps-repon auto-token ei tarvitse oikeuksia code repoon.

GitOps-repon workflow (ci-main.yml)

GitOps-repoon luodaan .gitea/workflows/ci-main.yml:

name: GitOps Update
run-name: "GitOps Service (${{ inputs.dispatch_id || 'manual' }})"
on:
  workflow_dispatch:
    inputs:
      file:
        required: true
        type: string
      yq_tpl:
        required: true
        type: string
      version:
        required: true
        type: string
      source_repo:
        required: true
        type: string
      source_commit:
        required: true
        type: string
      dispatch_id:
        required: false
        type: string
      git_tag_prefix:
        required: false
        type: string

env:
  INPUT_FILE: ${{ inputs.file }}
  YQ_TPL: ${{ inputs.yq_tpl }}
  VERSION: ${{ inputs.version }}
  SOURCE_REPO: ${{ inputs.source_repo }}
  SOURCE_COMMIT: ${{ inputs.source_commit }}
  GITOPS_REPO: ${{ github.repository }}
  GITOPS_BRANCH: ${{ github.ref_name }}
  GITEA_API_URL: ${{ gitea.server_url }}
  GIT_TAG_PREFIX: ${{ inputs.git_tag_prefix || '' }}

jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/checkout@v4
        with:
          repository: niko/gitea-ci-library
          path: .ci

      - name: Install yq
        run: |
          wget -qO /usr/local/bin/yq \
            https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
          chmod +x /usr/local/bin/yq

      - name: Run GitOps update
        env:
          GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
        run: |
          bash .ci/scripts/gitops-update.sh

Huomiot:

  • GITEA_TOKEN on Gitean auto-token — scopeutuu GitOps-repoon, riittää cloneen, committiin, pushiin ja commit-statusiin GitOps-repossa
  • run-name ja dispatch_id mahdollistavat dispatchaavan skriptin tunnistaa tämän workflow-runin yksiselitteisesti display_title-kentästä, vaikka samassa repossa olisi samanaikaisia ajoja
  • yq ladataan lennossa (kompromissi, ks. "Tuleva CI-kontti")

Tulossa: custom CI-kontti

Nykyinen job lataa yq:n lennossa. Myöhemmin rakennetaan oma kontti (ci-gitops), jossa on nodejs + git + yq valmiina. Sama patterni kuin ci-bats ja ci-cucumber. Ks. skills/ci-container-build/SKILL.md.

Code-repon dispatch-step

Code repo dispatchaa GitOps-repon workflown artifact buildin onnistuttua:

gitops-update:
  needs: [helm-build-push]
  if: success()
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4

    - uses: actions/checkout@v4
      with:
        repository: niko/gitea-ci-library
        path: .ci

    - name: Dispatch GitOps update
      id: dispatch
      env:
        GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
      run: |
        INPUTS=$(jq -nc \
          --arg file "dev/Chart.yaml" \
          --arg yq_tpl '(.dependencies[] | select(.name == "agent-platform-helm") | .version) = "{{VERSION}}"' \
          --arg version "${{ needs.check-version.outputs.version }}" \
          --arg source_repo "${{ github.repository }}" \
          --arg source_commit "${{ github.sha }}" \
          '{file: $file, yq_tpl: $yq_tpl, version: $version, source_repo: $source_repo, source_commit: $source_commit}')
        OUTPUT=$(bash .ci/scripts/dispatch-workflow.sh \
          "niko/agent-platform-gitops" \
          "ci-main.yml" \
          "main" \
          "$INPUTS" \
          "${{ fromJson(needs.load-config.outputs.env_json).GITEA_API_URL }}" \
          "${{ secrets.GITEA_TOKEN }}" \
          "30")
        echo "$OUTPUT"
        GITOPS_COMMIT=$(echo "$OUTPUT" | grep '^GITOPS_COMMIT=' | cut -d= -f2)
        echo "gitops_commit=$GITOPS_COMMIT" >> "$GITHUB_OUTPUT"

Multi-artifact pipeline (kontti + helm)

Yksi main-haaran build tuottaa usein sekä Docker-imagen että Helm-chartin. Kumpikin artefakti dispatchaa oman GitOps-päivityksensä rinnakkain:

gitops-helm:
  needs: [helm-build-push]
  if: success()
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - uses: actions/checkout@v4
      with:
        repository: niko/gitea-ci-library
        path: .ci
    - name: Update helm version
      id: helm
      run: |
        INPUTS=$(jq -nc \
          --arg file "dev/Chart.yaml" \
          --arg yq_tpl '(.dependencies[] | select(.name == "git-pages") | .version) = "{{VERSION}}"' \
          --arg version "${{ needs.check-version.outputs.version }}" \
          --arg source_repo "${{ github.repository }}" \
          --arg source_commit "${{ github.sha }}" \
          --arg git_tag_prefix "helm" \
          '{dispatch_id: "", file: $file, yq_tpl: $yq_tpl, version: $version, source_repo: $source_repo, source_commit: $source_commit, git_tag_prefix: $git_tag_prefix}')
        OUTPUT=$(bash .ci/scripts/dispatch-workflow.sh \
          "niko/gitea-ci-gitops-tests" "gitops-service.yaml" "main" \
          "$INPUTS" "${{ fromJson(needs.load-config.outputs.env_json).GITEA_API_URL }}" \
          "${{ secrets.GITOPS_DISPATCH_TOKEN }}" "30")
        echo "$OUTPUT"
        echo "helm_commit=$(echo "$OUTPUT" | grep '^GITOPS_COMMIT=' | cut -d= -f2)" >> "$GITHUB_OUTPUT"

gitops-docker:
  needs: [docker-build-push]
  if: success()
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    - uses: actions/checkout@v4
      with:
        repository: niko/gitea-ci-library
        path: .ci
    - name: Update docker tag
      id: docker
      run: |
        INPUTS=$(jq -nc \
          --arg file "dev/values.yaml" \
          --arg yq_tpl '.service.tag = "{{VERSION}}"' \
          --arg version "${{ needs.check-version.outputs.version }}" \
          --arg source_repo "${{ github.repository }}" \
          --arg source_commit "${{ github.sha }}" \
          --arg git_tag_prefix "docker" \
          '{dispatch_id: "", file: $file, yq_tpl: $yq_tpl, version: $version, source_repo: $source_repo, source_commit: $source_commit, git_tag_prefix: $git_tag_prefix}')
        OUTPUT=$(bash .ci/scripts/dispatch-workflow.sh \
          "niko/gitea-ci-gitops-tests" "gitops-service.yaml" "main" \
          "$INPUTS" "${{ fromJson(needs.load-config.outputs.env_json).GITEA_API_URL }}" \
          "${{ secrets.GITOPS_DISPATCH_TOKEN }}" "30")
        echo "$OUTPUT"
        echo "docker_commit=$(echo "$OUTPUT" | grep '^GITOPS_COMMIT=' | cut -d= -f2)" >> "$GITHUB_OUTPUT"

Kaksi dispatchia, kaksi eri tiedostoa, kaksi eri GIT_TAG_PREFIX-arvoa. Kummallakin on oma commit-status-linja ja oma summary-rivi. dispatch-workflow.sh hoitaa rinnakkaisuuden display_title-matchauksella.

GITEA_TOKEN dispatch-vaiheessa: Tarvitaan manuaalinen token, jolla on write-oikeus GitOps-repoon (esim. org-tason token). Code-repon auto-token ei oikeuta dispatchaamaan toiseen repoon. Token luodaan Giteassa: Settings → Applications → Generate Token ja asetetaan code-repoon Actions Secretiksi.

Commit-status dispatchin perusteella

dispatch-workflow.sh tulostaa GITOPS_COMMIT=<sha> stdoutiin onnistuneen GitOps-päivityksen jälkeen. Code repo parsii sen ja asettaa commit-statusin linkillä GitOps-committiin:

    - name: Set commit-status with GitOps link
      if: always()
      env:
        GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
        GITEA_API_URL: ${{ fromJson(needs.load-config.outputs.env_json).GITEA_API_URL }}
        GITOPS_COMMIT: ${{ steps.dispatch.outputs.gitops_commit }}
        VERSION: ${{ needs.check-version.outputs.version }}
      run: |
        GITOPS_URL="${GITEA_API_URL}/niko/agent-platform-gitops/commit/${GITOPS_COMMIT}"
        CTX="gitops/$(basename ${{ github.repository }})"
        DESC="Deploy to dev ${VERSION}"
        if [ -n "$GITOPS_COMMIT" ]; then
          bash .ci/scripts/report-status.sh success "$DESC" "$CTX" "" "$GITOPS_URL"
        else
          bash .ci/scripts/report-status.sh success "$DESC" "$CTX"
        fi

dispatch-workflow.sh palauttaa:

  • exit 0 = GitOps-päivitys onnistui (+ GITOPS_COMMIT=<sha>)
  • exit 1 = GitOps-päivitys failasi
  • exit 124 = aikakatkaisu (360 min oletus)

Loppuraportti (report-summary)

Code-repon viimeinen job (report-summary) lisää GitOps-päivityksestä rivin GITHUB_STEP_SUMMARYyn:

    - name: GitOps summary
      if: always()
      env:
        GITEA_API_URL: ${{ fromJson(needs.load-config.outputs.env_json).GITEA_API_URL }}
        GITOPS_COMMIT: ${{ steps.dispatch.outputs.gitops_commit }}
        VERSION: ${{ needs.check-version.outputs.version }}
      run: |
        if [ -n "$GITOPS_COMMIT" ]; then
          LINK="${GITEA_API_URL}/niko/agent-platform-gitops/commit/${GITOPS_COMMIT}"
        else
          LINK="#"
        fi
        cat >> "$GITHUB_STEP_SUMMARY" << 'GITOPS'

        ## GitOps updates

        | Component | Version | Status | Commit |
        |-----------|---------|--------|--------|
        | agent-platform-helm | __VERSION__ | __STATUS__ | [link](__LINK__) |
        GITOPS
        sed -i "s|__VERSION__|${VERSION}|; s|__STATUS__|${{ job.status }}|; s|__LINK__|${LINK}|" \
          "$GITHUB_STEP_SUMMARY"

Secretit ja tokenit

Secret Missä Scope Kuvaus
GITEA_TOKEN (auto) Code repo Vain code repo Asettaa commit-statusin dispatchin jälkeen
GITEA_TOKEN (auto) GitOps repo Vain GitOps repo Klooni, push, commit-status GitOps-repossa
GITOPS_DISPATCH_TOKEN (manuaalinen) Code repo Write GitOps-repoon Dispatchaa GitOps-repon workflow

Tokenin luonti:

  1. Gitea → SettingsApplicationsGenerate Token
  2. Valitse repo-oikeudet: valitse GitOps-repo, anna write-oikeudet
  3. Token asetetaan code-repoon: {repo} → Settings → Actions Secrets
  4. Salaisuuden nimi: esim. GITOPS_DISPATCH_TOKEN

Provider-skriptit

scripts/gitops-update.sh

Ajaan GitOps-repon workflow'ssa. Päivittää konfiguraatiotiedoston yq:llä, committaa ja pushaa. Asettaa commit-statuksen vain GitOps-repoon.

Input-ympäristömuuttujat:

Muuttuja Pakollinen Kuvaus
INPUT_FILE Kyllä Tiedosto GitOps-repossa (esim. dev/Chart.yaml)
YQ_TPL Kyllä yq-lauseke {{VERSION}}-placeholderilla
VERSION Kyllä Uusi versio (esim. 0.2.3)
SOURCE_REPO Kyllä Code-repo slug (esim. org/app)
SOURCE_COMMIT Kyllä Code-repon commit SHA
GITOPS_REPO Kyllä GitOps-repo slug
GITEA_API_URL Kyllä Gitean API-URL
GITEA_TOKEN Kyllä Gitea API-token (write GitOps-repoon)
GITOPS_BRANCH Ei Branch (oletus main)
GIT_TAG_PREFIX Ei Komponentin tag-prefix status-nimeämiseen (esim. agent-platform-helm)
GITOPS_CLONE_URL Ei Yliajaa clone-URL (esim. eri protokolla)
GITOPS_TARGET_DIR Ei Yliajaa clone-kohdehakemisto

Commit-status muoto:

GitOps-repoon asetetaan commit-status:

Kenttä Formaatti Esimerkki
Context {repo}/{GIT_TAG_PREFIX} {RUN_ID} tai {repo} {RUN_ID} gitea-ci-library/agent-platform-helm 473
Description Install to {env} {version} Install to dev 0.2.0
Target URL Linkki code-repon committiin /niko/gitea-ci-library/commit/abc123

Jos tiedosto on jo halutussa versiossa (ei muutoksia), status saa descriptionin Install to {env} {version} — no change. Commit-pushia ei tehdä, GitOps-repo pysyy muuttumattomana.

  • {env} parsitaan INPUT_FILE:stä (dev/Chart.yamldev)
  • {repo} parsitaan SOURCE_REPO:sta (niko/gitea-ci-librarygitea-ci-library)
  • {GIT_TAG_PREFIX} tulee env-varista (sama kuin gitea-env.conf:ssa)

scripts/dispatch-workflow.sh

Dispatchaa workflow_dispatchin kohderepoon ja pollaa valmistumista. Generoi automaattisesti dispatch_id-tunnisteen, lisää sen dispatch- inputteihin ja tunnistaa workflow-runin kohdereposta display_title- kentän perusteella. Toimii luotettavasti vaikka samassa repossa olisi useita samanaikaisia dispatch-attribuutioita.

Argumentit:

# Pakollinen Kuvaus
1 Kyllä Kohderepo (esim. niko/agent-platform-gitops)
2 Kyllä Workflow-tiedosto (esim. ci-main.yml)
3 Kyllä Branch/ref
4 Kyllä Inputs JSON
5 Kyllä Gitea API URL
6 Kyllä Gitea token
7 Ei Aikakatkaisu minuutteina (oletus 360)

Kutsujan ei tarvitse välittää dispatch_id:tä — skripti generoi sen itse ja lisää inputteihin ennen dispatchia.

[skip ci]

Commit-viestissä on [skip ci], joka estää GitActions-runneria triggeröimästä uutta CI-ajoa GitOps-repoon pushista. Näin vältetään ääretön trigger-loop.

Race condition

dispatch-workflow.sh tunnistaa jokaisen dispatchatun runin uniikilla dispatch_id-tunnisteella display_title-kentästä. Vaikka useampi artifakti dispatchaisi samaan aikaan ja useita workflow-runeja olisi käynnissä rinnakkain, jokainen skripti löytää oikean runinsa.

Sääntöjä

  1. Token ei kirjoita code repoon. GitOps-repon workflow ei tarvitse oikeuksia code repoon. Kaikki status-kutsut kohdistuvat vain GitOps-repoon. Code repo asettaa oman statusnsa itse.
  2. Ei provider-workflowta. GitOps-päivitys ei ole reusable workflow. GitOps-repo ajaa scripts/gitops-update.sh:n suoraan.
  3. Vain workflow_dispatch. GitOps-repon workflow:ta ei triggeröidä pushista — se laukeaa vain dispatch-kutsusta.
  4. **Dispatch ei palauta tarkkaa SHA:**ta. Code repo ei tiedä GitOps- commitin SHA:ta ennen dispatch-valmistumista. Status asetetaan dispatchin exit-koodin perusteella, ei GitOps-commitin tiedoilla.
  5. dispatch_id on pakollinen kohde-workflow'ssa — ilman sitä dispatch-workflow.sh ei löydä oikeaa runia moniajo-tilanteessa.
  6. [skip ci] commit-viestissä. Pakollinen trigger-loopin estoon.