🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)
🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)

🔧 Programmierung 🕛 kürzlich 6 Min Lesezeit
0

From git push to Fine-Tuned Model in Production

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

At some point in every engineer's life, they sit down and think: "You know what this fine-tuning pipeline needs? More YAML." That moment arrived for me, and the result is GPU infrastructure, entirely from a GitHub workflow.









The Idea



I wanted one thing: click a button in GitHub, have a real GPU spin up, fine-tune a model, package it into a serving image, deploy it to a live endpoint, prove it works, and clean everything up — with zero manual steps and no leaked cloud resources. No Jupyter notebooks saved as "final_v3_REAL.ipynb". No SSH-ing into a VM to babysit training. Just a workflow that does the whole thing and gets out of your way.



The result is demo-run-job.yml: it QLoRA-fine-tunes Qwen2.5-0.5B on wikitext for 30 steps with Axolotl, bakes the LoRA adapters into a vLLM serving image, deploys it to a Nebius Endpoint, and smoke-tests it — all triggered by a single workflow_dispatch click.



The pipeline runs across five GitHub jobs: submit, wait, deploy, try, and cleanup. State that must cross job boundaries — bucket name, image ref, job ID, endpoint URL — travels as job outputs.









The Five Acts of This Drama






Act 1 — submit: Everything Happens Here



The submit job is where the magic (and most of the YAML) lives. It:




  1. Writes an Axolotl config inline — the workflow is the single source of truth. No external config file to lose.

  2. Writes a train-and-push.sh script inline — yes, a full Bash script, heredoc'd into the workflow. It fine-tunes with Axolotl, packages the adapters into a tar layer, installs crane (a daemonless container registry client, because the GPU job has no Docker daemon), and pushes vllm/vllm-openai:latest + the adapter layer to the Nebius Container Registry.

  3. Provisions a fresh S3 bucket per run, uploads both files, and creates the Nebius Job.



The auth story is pleasantly clean: a setup action configures a key-based CLI profile, and an auth action mints a short-lived NEBIUS_IAM_TOKEN for the SDK path. No long-lived credentials sitting in your repo — just a token that expires before you finish reading this post.




CODE
- name: Submit fine-tune + image push
id: submit
uses: ./actions/submit-job
with:
name: demo-axolotl-${{ github.run_id }}
image: ${{ vars.NEBIUS_JOB_IMAGE || 'docker.io/axolotlai/axolotl:main-20260309-py3.11-cu128-2.9.1' }}
platform: ${{ inputs.platform }}
preset: ${{ inputs.preset }}
command: bash
timeout: 1h
env: |
BASE_IMAGE=${{ vars.NEBIUS_VLLM_IMAGE || 'docker.io/vllm/vllm-openai:latest' }}
IMAGE=${{ steps.image.outputs.image }}
REGISTRY=${{ steps.image.outputs.registry }}
REGISTRY_TOKEN=${{ env.NEBIUS_IAM_TOKEN }}
mounts: ${{ steps.bucket.outputs.bucket-id }}:/workspace/data:rw
disk-size: ${{ inputs.disk-size }}
preemptible: true
args: -c "bash /workspace/data/train-and-push.sh"









Act 2 — wait: The Anxious Polling Phase



This job does one thing: stream the GPU job's logs and poll it to a terminal state. It also handles a subtle but expensive problem — if you cancel the GitHub workflow, the Nebius Job keeps running (and keeps billing you) unless you explicitly forward the cancellation:




CODE
- name: Wait for fine-tune + image push
id: wait
uses: ./actions/wait-for-job
with:
job-id: ${{ needs.submit.outputs.job-id }}
stream-logs: true
poll-interval: 10
timeout: 3600

- name: Cancel job on workflow cancellation
if: cancelled() && needs.submit.outputs.job-id != ''
uses: ./actions/cancel-job
with:
job-id: ${{ needs.submit.outputs.job-id }}






That if: cancelled() guard has saved me from some spicy cloud bills.






Act 3 — deploy: It Lives



Once wait confirms the job succeeded — meaning the vLLM image with baked-in adapters is in the registry — deploy creates a Nebius Endpoint and polls it to serving. wait: false is intentional: it means the endpoint ID is published even if the endpoint never becomes ready, which lets cleanup tear it down safely regardless.




CODE
- name: Deploy endpoint
id: deploy
uses: ./actions/deploy-endpoint
with:
name: demo-axolotl-${{ github.run_id }}
image: ${{ needs.submit.outputs.image }}
port: 8000
public: true
preset: ${{ inputs.endpoint-preset }}
platform: ${{ inputs.endpoint-platform }}
disk-size: ${{ inputs.endpoint-disk-size }}
project-id: ${{ vars.NEBIUS_PROJECT_ID }}
wait: false

- name: Wait for endpoint
id: endpoint
uses: ./actions/wait-for-endpoint
with:
endpoint-id: ${{ steps.deploy.outputs.endpoint-id }}
poll-interval: 10
timeout: 1800









Act 4 — try: Does It Actually Work?



The smoke test is beautifully minimal:




CODE
curl -fsS --retry 30 --retry-delay 10 "$URL/health"
curl -fsS -X POST "$URL/v1/completions" \
-H 'Content-Type: application/json' \
-d '{"model": "demo", "prompt": "The quick brown fox", "max_tokens": 16}'






demo is the --lora-modules name that train-and-push.sh baked into the image entrypoint. You fine-tuned it, you named it, now you serve it. Deeply personal.






Act 5 — cleanup: if: always()



The cleanup job has needs on all four upstream jobs and — critically — if: always(). This is the move that separates people who have been surprised by a $200 cloud bill from people who haven't:




CODE
cleanup:
needs: [submit, wait, deploy, try]
if: always()
steps:
- name: Delete endpoint
if: needs.deploy.outputs.endpoint-id != ''
uses: ./actions/delete-endpoint
with:
endpoint-id: ${{ needs.deploy.outputs.endpoint-id }}

- name: Delete bucket
if: needs.submit.outputs.bucket-id != ''
uses: ./actions/delete-bucket
with:
bucket: ${{ needs.submit.outputs.bucket-name }}
bucket-id: ${{ needs.submit.outputs.bucket-id }}






Endpoint dies. Bucket dies. The pushed image stays in the registry, tagged with the run ID, ready to be redeployed. Responsible MLOps.









The Actions Themselves



The reusable building blocks are small and composable. The key ones:





  • setup — installs the nebius CLI, configures a key-based profile, exports NEBIUS_PROJECT_ID and NEBIUS_SERVICE_ACCOUNT_ID for downstream steps.


  • auth — mints a short-lived IAM token via OIDC (keyless, recommended) or a service-account key.


  • submit-job + wait-for-job — decoupled create and poll, so you can fan out or gate between them.


  • deploy-endpoint + wait-for-endpoint + delete-endpoint — the full endpoint lifecycle.


  • create-bucket, upload-object, delete-bucket — the storage trio, all using short-lived S3 keys minted on the fly, no stored S3 credentials required.



The design philosophy: one action per resource, no hidden orchestration, no magic. If you want a rigid pipeline, the demo is there. If you want to mix and match — say, fine-tune in one workflow and deploy in another — the primitives are waiting.









Try It Yourself



The repo is at github.com/piotrjanik/nebius-actions. You'll need a Nebius project, a service account with ai.editor role, and the patience to fill in five repo variables and one secret. The README has the exact nebius iam commands to set it all up.



Then click Run workflow, pick your GPU preset, and watch a 500M-parameter model get fine-tuned and deployed while you make coffee. That's the dream. That's the YAML.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Hackers Just Poisoned the Rust Supply Chain | Threat Wire
1 Quelle
Hackers Found a Way Into Humanoid Robots | Threat Wire
1 Quelle
Bits und so #1021 (Passwort für Laufwerk)
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten From git push to Fine-Tuned Model in Production

Thematisch verwandte Begriffe: From, push, FineTuned, Model · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...