A model launch post is not a GitLab environment.
I keep those layers apart when the news cycle speeds up.
Are you about to wire a comment bot into production?
This week's feeds are full of agent demos.
Your pipeline is still a rules file, a runner, and an environment record.
I wrote this to split those layers before any trial starts.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
Operator notes describe free model access and a free server option.
I am not copying a token total or a machine size.
I am also not stating a time limit or a region.
Confirm those details on the current product pages first.
Posting a review comment means you deployed something real.
GitLab environments track deployments, stops, and sometimes a public URL.
A comment is an API write, not an environment entry.
Keep the bot out of environment unless it actually deploys.
Use a plain job with merge request rules instead.
Fail closed when the model pin is absent.
ai_note_check:
stage: test
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- test -n "$MODEL_REF" || { echo "missing MODEL_REF"; exit 2; }
- echo "would_review=1" > review-plan.txt
artifacts:
paths:
- review-plan.txt
expire_in: 3 days
That job fails closed when the pin is missing.
It does not call a model, and it does not touch production.
Treat the file as a plan, not as a review result.
A resource group keeps the same model for every run.
People copy that key and skip the variable store.
The job name then pretends to be a version lock.
A resource group limits concurrent jobs that share one name.
It does not select a model id or a prompt file.
It also does not select a vendor account for you.
Pin the model with a protected variable or a committed file.
Use a resource group only to avoid overlapping comment writes.
If you need both controls, configure them on separate lines.
ai_note_check:
resource_group: mr-notes-$CI_MERGE_REQUEST_IID
Ask yourself this before you copy that resource key.
Do you need mutual exclusion, or do you need a version pin?
A yes to both still requires two different settings.
Killing an AI job is harmless because the job is interruptible.
The flag looks like a safety property in review.
It is only a cancellation hint for newer pipelines.
The flag lets a newer pipeline cancel the older job.
It does not roll back a comment that job already posted.
Make the side effect idempotent, or skip the remote write.
Record the commit SHA in the note body you control.
Build the key before any client code runs.
note_key="${CI_MERGE_REQUEST_IID:-0}-${CI_COMMIT_SHORT_SHA:-none}"
printf 'note_key=%s\n' "$note_key"
Would a second run post a second note with a new key?
If yes, your retry story is not done yet.
Fix the key before you enable a live token.
The free server option behaves like an environment stop action.
That story collapses two owners into one sentence.
Cleanup then belongs to nobody on the team.
An environment on_stop job is your cleanup hook on your runner.
A free server is only what the current offer says it is.
I will not describe its hardware, region, or lifetime here.
Name the cleanup owner before you start any trial.
If the offer does not name a stop action, you still need one.
Your runner remains the place that executes that hook.
stop_review_scratch:
stage: cleanup
rules:
- if: $CI_COMMIT_BRANCH == "ai-pin-check"
when: manual
script:
- rm -f review-plan.txt
- echo "local scratch removed"
That example only deletes a local workspace file.
It is not a receipt that a remote process stopped.
Keep the manual job until you own a real stop path.
A public agent repo automatically uses your clone strategy.
The badge feels like a configuration inheritance.
Your runner never reads the badge that way.
GIT_STRATEGY is a GitLab runner variable on your own job.
The upstream license does not set it for your pipeline.
A news post does not set it either.
Set fetch depth and strategy in the job you own.
Then review the client for unexpected network calls.
Unknown outbound behavior is a fail on protected branches.
variables:
GIT_STRATEGY: fetch
GIT_DEPTH: "20"
Fill that network judgment from the repo you cloned.
Do not fill it from this FAQ or from a launch thread.
Write unknown when the README does not answer you.
A token number in a post is your pipeline budget.
The figure then gets pasted into an environment description.
Next week the page can change while your YAML stays.
Budgets change, and this article is not a pricing source.
Operator notes say free model access exists, plus a free server option.
They do not authorize me to freeze a token count here.
Paste the live figure into the merge request body.
Include the date you actually read that page.
Reload the page on the day you enable the job.
If the page and this FAQ disagree, trust the page.
A blog number is not an environment quota.
An undated repost is not a better source than the page.
I accept a job URL, a commit SHA, and a dated offer note.
I do not accept a chat screenshot as pipeline proof.
I do not accept an undated token figure from a repost.
Primary docs beat a secondary recap, including this one.
If you cannot link the page, write unknown in the table.
Unknown stays a fail for any protected branch job.
Use this table on the merge request itself.
I have not scored a real fleet with it.
The rows are gates, not a quality score for model prose.
| Check | Pass looks like | Fail looks like |
|---|---|---|
| No production environment | YAML lacks environment: |
Bot listed as a production deploy |
| Model pin is separate | MODEL_REF protected or committed |
Pin exists only in a chat |
| Side effect is idempotent | Note key includes the SHA | Retries can duplicate notes |
| Cleanup owner is named | Manual job or your on_stop |
Free server assumed as cleanup |
| Offer date is in the MR | Dated line from the live docs | Number copied from an old post |
| Clone settings are local | GIT_STRATEGY set on the job |
Public repo assumed to inherit it |
Three failed rows means you stop the trial.
A clean table still means a scratch branch only.
Production stays out of scope until a human owns each row.
This plan is a proposal for a scratch project.
I did not execute it while writing this draft.
Label the pipeline result as unexecuted until you run it.
ai-pin-check. MODEL_REF and confirm the job exits 2.verify-me only.
sample = """
ai_note_check:
stage: test
script: ["true"]
"""
bad = "environment:" in sample and "production" in sample
print("production_environment", bad)
Extend that check to your real file before you trust it.
A green printout is not a GitLab lint result.
Run the official linter if your instance allows that call.
These commands are reminders, not a captured session.
I have not run them against your group.
test -n "${MODEL_REF:-}" && echo "ref present" || echo "ref missing"
if test -n "${MODEL_TOKEN:-}"; then echo "token set"; else echo "token unset"; fi
A missing ref should stop the job.
A set token should print status only, never the secret.
If your log shows the secret, rotate it before the next push.
Use free model access for a human trial on a fake diff.
Use the free server option only when the live offer matches policy.
The product does not become your environment, your runner, or your audit log.
If you need those roles, configure them in GitLab yourself.
Remove every product mention and this checklist should still help.
That is the bar I want for a trial note like this.
Skip the trial when the repository holds regulated data.
Skip it when policy requires a signed quota or a fixed region.
Skip it when you only want to chase this week's model headline.
A headline will not name your cleanup owner.
A headline will not register a runner for you either.
Wait until the table has an owner for every fail.
I do not know your protected branch rules or your runner tags.
I did not measure latency, cost, or comment quality.
Free access can change or disappear without this page updating.
The script will not detect a malicious prompt by itself.
It only catches the identity mix-ups listed above.
Add your own data-policy review before any real diff leaves the laptop.
Open the YAML for the job you wanted to call a deployment.
Which table row fails first on that job?
If a trial still helps, read the current MonkeyCode pages.
Date that reading in the merge request, then run the fail-closed job on a scratch branch.