Evet, GitLab CI sizin URL kısaltıcınız olarak çalışabilir. curl ve tek bir API anahtarı olan bir iş, her merge request için bir kısa bağlantı oluşturabilir, onu review app'e yönlendirebilir ve bir etiket gönderdiğinizde sabit bir latest bağlantısını yeni sürüme taşıyabilir. Yaklaşık kırk satır YAML. Bugün çalışıyor.
İnsanların yanlış yaptığı kısım HTTP çağrısı değil. Anahtar: nerede durduğu, hangi pipeline'ların onu okuyabildiği ve bir dal işi onu sızdırırsa ne kadar zarar verebileceği. Bu yüzden bu rehber, .gitlab-ci.yml'in kendisi kadar değişkenlere ve kapsamlandırmaya da zaman ayırıyor. Uzun ömürlü bağlantıları bildirimsel olarak yönetmeyi tercih ederseniz kısa bağlantılar için Terraform yaklaşımı daha uygundur; pipeline'lar kodla birlikte doğup emekli olan bağlantılara yakışır.
Baştan bir durum notu. Elido'nun yerel GitLab entegrasyonu geliyor, henüz yayında değil ve aşağıdakilerin hiçbiri ona bağlı değil. Yönetilen sürümü mü istiyorsunuz? GitLab entegrasyon sayfasında bekleme listesi var.
Bir GitLab CI URL Kısaltıcı İşi Ne Yapar
Bir pipeline kısaltıcısı üç şey yapar ve yalnızca üç şey. Slug yoksa bir bağlantı oluşturur, varsa hedefi günceller ve işaret ettiği şey ortadan kalkınca bağlantıyı devre dışı bırakır. Analitik ve QR kodları Elido tarafında kalır.
API yüzeyi küçük. Bağlantılar /v1/workspaces/{workspace_id}/links altında yaşar: POST bir tane oluşturur ve bir domain_id ile bir destination_url ister, PATCH /links/{link_id} var olan bir bağlantının alanlarını değiştirir, GET /links?q= ise slug, hedef ya da başlığa göre arar. Kimlik doğrulama tek bir başlıktır: Authorization: Bearer elido_.... Anahtar, panelin API anahtarları sayfasından gelir.
Sözleşmenin tamamı bu. API ve SDK genel bakışı diğer uç noktaları listeler, ama bir pipeline nadiren bu üçünden fazlasına ihtiyaç duyar.
Anahtarı Maskeli ve Korumalı Değişken Olarak Saklamak
GitLab size burada önem taşıyan iki anahtar verir ve farklı işler görürler. Maskeleme, bir değeri iş günlüklerinde gizler. Koruma ise değeri hangi pipeline'ların hiç alacağını belirler.
Settings, CI/CD, Variables bölümünde değişkeni oluştururken Masked and hidden seçeneğini seçin. Hidden (GitLab 17.6'dan beri genel kullanıma açık), ayarlar sayfasında hiç kimsenin değeri sonradan görüntüleyememesi demektir; bir kimlik bilgisi için istediğiniz de budur. GitLab CI/CD değişkenleri dokümanları maskelenmiş bir değerin koşullarını listeler: tek satır, boşluk yok, en az 8 karakter. Elido anahtarları elido_ ve ardından base32 şeklindedir, dolayısıyla uygundur.
Aynı sayfa sınır konusunda açık sözlü: maskeleme "kötü niyetli kullanıcıların değişken değerlerine erişmesini önlemenin garantili bir yolu değildir." Değişkeni base64 ile kodlayıp yazdıran bir iş maskenin yanından rahatça geçer. Maskelemeyi erişim denetimi değil, günlük hijyeni olarak görün.
Erişim denetimi korumadır. Korumalı bir değişken yalnızca korumalı dallardaki ya da korumalı etiketlerdeki pipeline'lara ulaşır; bu da her ekibin ilk haftasında yaşadığı soruna yol açar: merge request pipeline'ınız bir özellik dalında çalışır, bu yüzden korumalı anahtar boş bir dize olarak gelir ve iş, yazım hatası gibi görünen bir 401 ile başarısız olur.
Bunu tek anahtarı zayıflatmak yerine iki anahtarla çözerdim. Kullanacağım düzen şöyle:
| Değişken | Görünürlük | Korumalı | Okuyan |
|---|---|---|---|
ELIDO_PREVIEW_KEY | Masked and hidden | Hayır | Merge request pipeline'ları |
ELIDO_RELEASE_KEY | Masked and hidden | Evet | Korumalı etiketlerdeki etiket pipeline'ları |
ELIDO_PREVIEW_WS, ELIDO_RELEASE_WS | Görünür | Hayır | Herhangi bir iş (kimlikler sır değildir) |
ELIDO_DOMAIN_ID, SHORT_HOST | Görünür | Hayır | Herhangi bir iş |
Önizleme anahtarı, yalnızca inceleme bağlantılarını tutan ayrı bir çalışma alanına aittir. Bir dal gönderebilen herkes, prensipte korumasız bir değişkeni dışarı sızdırabilir; bu yüzden erişebilecekleri en kötü şeyin bir yığın geçici mr-142 bağlantısı olduğundan emin olun. Sürüm anahtarı ise gerçek çalışma alanınızda durur ve yalnızca koruduğunuz etiketlerde çalışır.
İki anahtara da Editor rolünü ve bir son kullanma tarihi verin; önizleme anahtarı için 90 gün uygundur. Editor, bağlantı yazabilen en düşük hazır roldür ve bağlantıları silebilir de; API anahtarları hazır rollerden birini alır ve tam bu durum için yalnızca oluşturma ve güncelleme yapabilen bir hazır rol isterdim; henüz yok. Etki alanını gerçekten sınırlayan şey çalışma alanı ayrımıdır.
Kısa Bağlantı Oluşturan Çalışan Bir .gitlab-ci.yml İşi
Ortak parça şu: slug'ı arayan, yoksa bağlantıyı oluşturan, varsa yamalayan bir upsert. Onu gizli bir işe koyun ve genişletin.
.elido_upsert:
image: alpine:3.20
before_script:
- apk add --no-cache curl jq
script:
- API="https://api.elido.app/v1/workspaces/${ELIDO_WS}"
- AUTH="Authorization: Bearer ${ELIDO_KEY}"
- |
find_id() {
curl -sS --fail-with-body -H "$AUTH" "$API/links?q=${SLUG}&limit=50" |
jq -r --arg s "$SLUG" --argjson d "$ELIDO_DOMAIN_ID" \
'.items[] | select(.slug == $s and .domain_id == $d) | .id' | head -n1
}
ID="$(find_id)"
if [ -z "$ID" ]; then
CODE=$(curl -sS -o resp.json -w '%{http_code}' -X POST "$API/links" \
-H "$AUTH" -H "Content-Type: application/json" \
-H "Idempotency-Key: ${CI_PIPELINE_ID}-${SLUG}" \
-d "$(jq -n --arg s "$SLUG" --arg u "$TARGET" --argjson d "$ELIDO_DOMAIN_ID" \
'{domain_id: $d, slug: $s, destination_url: $u, tags: ["ci"]}')")
case "$CODE" in
201) ;;
409) ID="$(find_id)" ;; # another pipeline created it first
*) cat resp.json; exit 1 ;;
esac
fi
if [ -n "$ID" ]; then
curl -sS --fail-with-body -X PATCH "$API/links/$ID" \
-H "$AUTH" -H "Content-Type: application/json" \
-d "$(jq -n --arg u "$TARGET" '{destination_url: $u, status: "active"}')"
fi
- echo "SHORT_URL=https://${SHORT_HOST}/${SLUG}" >> link.env
artifacts:
reports:
dotenv: link.env
q araması bir alt dize eşleşmesidir; bu yüzden jq filtresi onu tam slug ve tam alan adına daraltır. O olmadan web-mr-14 araması web-mr-142 sonucunu da seve seve döndürürdü. domain_id değerinizi bir kez GET /v1/workspaces/{id}/domains ile alın ve düz bir değişken olarak saklayın; özel alan adları üzerinden kurulmuş markalı bir ana makine, bir merge request'te genel olandan daha iyi okunur.
Merge Request Başına Review App Kısa Bağlantıları
Review app'ler, GitLab'ın dal ya da merge request başına geçici ortama verdiği addır ve review app dokümanları onları dinamik ortamlar üzerine kurar. Adresleri genelde çirkindir: bir karma, bir ad alanı, bir bulut sağlayıcısının ana makine adı. go.example.com/web-mr-142 gibi bir kısa bağlantı ise günlük toplantıda yüksek sesle söyleyebileceğiniz bir şeydir.
review_link:
extends: .elido_upsert
stage: deploy
needs: [deploy_review]
variables:
ELIDO_KEY: $ELIDO_PREVIEW_KEY
ELIDO_WS: $ELIDO_PREVIEW_WS
SLUG: "${CI_PROJECT_NAME}-mr-${CI_MERGE_REQUEST_IID}"
TARGET: "https://${CI_ENVIRONMENT_SLUG}.review.example.com"
environment:
name: review/$CI_COMMIT_REF_SLUG
url: $SHORT_URL
on_stop: stop_review_link
auto_stop_in: 1 week
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
İşin püf noktası dotenv raporu. Upsert SHORT_URL değerini link.env dosyasına yazar, GitLab onu geri okur ve environment:url kısa bağlantı olur; böylece merge request üzerindeki View app düğmesi ham ana makine adı yerine web-mr-142 adresini açar. Ortam dokümanları bu dinamik URL kalıbını anlatır.
CI_MERGE_REQUEST_IID proje başına benzersizdir ve merge request'in ömrü boyunca hiç değişmez; bu yüzden aynı MR'a yapılan her push aynı slug'a düşer ve upsert çoğaltmak yerine yamalar. Farklı bir anahtar isterseniz tam liste önceden tanımlı değişkenler referansında.
Temizlik, action: stop içeren bir iştir. Başlatma işinin rules bölümünü paylaşmak zorundadır, yoksa GitLab onu otomatik tetikleyemez:
stop_review_link:
image: alpine:3.20
stage: deploy
variables:
GIT_STRATEGY: none
SLUG: "${CI_PROJECT_NAME}-mr-${CI_MERGE_REQUEST_IID}"
script:
- apk add --no-cache curl jq
- API="https://api.elido.app/v1/workspaces/${ELIDO_PREVIEW_WS}"
- ID=$(curl -sS -H "Authorization:
Bearer ${ELIDO_PREVIEW_KEY}" "$API/links?q=${SLUG}" |
jq -r --arg s "$SLUG" --argjson d "$ELIDO_DOMAIN_ID" '.items[] | select(.slug == $s and .domain_id == $d) | .id' | head -n1)
- '[ -z "$ID" ] || curl -sS --fail-with-body -X PATCH "$API/links/$ID" -H "Authorization: Bearer ${ELIDO_PREVIEW_KEY}" -H "Content-Type: application/json" -d "{\"status\":\"disabled\"}"'
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
when: manual
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
Silmek yerine devre dışı bırakıyorum. Devre dışı bir bağlantı tıklama geçmişini korur ve biri MR'ı yeniden açarsa sonraki pipeline aynı upsert ile onu tekrar active yapar. GIT_STRATEGY: none oradadır, çünkü o noktada dal silinmiş olabilir.
Review app sayınız sürüm sayınızı on kat aşıyorsa plan sınırları tam orada ısırmaya başlar. Bunu yoğun bir monorepo'ya bağlamadan önce fiyatlandırma sayfasındaki bağlantı kotasına bakın ve denerken önizlemeler için ücretsiz bir çalışma alanı başlatın.
Etiket Pipeline'larında Sabit Bir Latest Bağlantısını Yeniden Yönlendirmek
İkinci kalıp etiketlerde çalışır ve review bağlantısının tersini yapar: hiç değişmeyen tek bir slug, hedefi her sürümle ileri taşınır. README'niz sonsuza dek go.example.com/cli-latest adresine işaret edebilir.
latest_link:
extends: .elido_upsert
stage: release
variables:
ELIDO_KEY: $ELIDO_RELEASE_KEY
ELIDO_WS: $ELIDO_RELEASE_WS
SLUG: "cli-latest"
TARGET: "${CI_PROJECT_URL}/-/releases/${CI_COMMIT_TAG}"
rules:
- if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/
Kuralı v* gibi korumalı bir etiket kalıbıyla eşleştirin; böylece onu tetikleyen etiketleri yalnızca bakımcılar oluşturabilir. Aksi hâlde korumalı anahtar orada olmaz ve iş güvenli biçimde başarısız olur; istediğiniz davranış da budur. Kalıcı bir sürüm başına bağlantı da isterseniz aynı işi SLUG: "cli-${CI_COMMIT_REF_SLUG}" ile ikinci kez çalıştırın; bu, v1.4.0 değerini cli-v1-4-0 yapar.
Bir latest bağlantısında redirect_status değerini 301 yapmayın. 301, tarayıcıların önbelleğe almasına izin verilen kalıcı bir sözdür ve latest bağlantısı bu sözü her sürümde bozar. Alanı boş bıraktığınızda Elido varsayılan olarak 302 kullanır; 301 ve 302 yönlendirmeleri yazımız ise seçimin gerçekten sorun çıkardığı durumları anlatır.
Dürüst bir uyarı: değişen bir hedefin her uç konuma ulaşması birkaç dakika sürebilir; bu yüzden kısa bağlantıya hemen bir sonraki saniyede curl atan bir duman testi hâlâ önceki sürümü görebilir. Bunun yerine API yanıtı üzerinden doğrulama yapın ya da Location başlığını kontrol etmeden önce bekleyin.
Idempotency, Yeniden Denemeler ve Hız Sınırları
Pipeline'lar yeniden dener. Runner'lar işin ortasında ölür, biri kırmızı bir işte Retry'a tıklar ve otuz saniye arayla gelen iki push birbiriyle yarışır. Yukarıdaki upsert üçüne de dayanır ve nedenini bilmeye değer.
Idempotency-Key başlığı yeniden denenen bir POST'u güvenli kılar: API başarılı bir yanıtı 24 saat önbelleğe alır ve aynı anahtar için yeniden oynatır; böylece aynı pipeline'ın yeniden denemesi hata yerine orijinal bağlantıyı geri alır. Anahtarı CI_PIPELINE_ID ve slug'dan oluşturmak, bir pipeline içindeki yeniden denemelerin yeniden oynatılmasını, yeni bir pipeline'ın ise yeni bir deneme almasını sağlar. 409 dalı iki farklı pipeline arasındaki yarışı ele alır; ara-sonra-yamala yolu ise ikinci bir çalıştırmayı fiilen etkisiz kılar.
Hız sınırları, çalışma alanı başına sınırın üstüne anahtar başına uygulanır ve yepyeni çalışma alanlarının itibar kazanırken daha düşük bir günlük bağlantı oluşturma tavanı da vardır. Bir avuç merge request bunu fark etmez. Aynı anda kırk review app ayağa kaldıran bir monorepo fark edebilir; bu yüzden 429'u GitLab'ın retry anahtar sözcüğüyle yeniden denenebilir sayın, geçici hata değil plan sınırı anlamına gelen 402'de ise yüksek sesle başarısız olun. Kısaltıcı API'leri için hız sınırları ve idempotency yazımız, bir CI işinin ihtiyaç duyduğundan daha ayrıntılı biçimde geri çekilmeyi ele alıyor.
Tam eşleşme yapan jq filtresini atlarsanız, MR 14'ün pipeline'ı sessizce MR 142'nin bağlantısını yamalar. İlk belirti genelde şaşkın bir tasarımcıdır. Filtreyi tutun.
YAML içindeki kabuk betiği hantallaşırsa aynı çağrılar depoya koyduğunuz bir betiğe düzgünce sarılabilir; URL kısaltıcı CLI rehberi bu biçimi gösterir.
Temel yazıyı okuyun → Terraform olarak kısa bağlantılar: bağlantıları kod olarak yönetmek
Blogda İlgili Yazılar
- URL kısaltıcı API hızlı başlangıcı - yukarıdaki her işin çağırdığı REST yüzeyi.
- Kısaltıcı API'leri için hız sınırları ve idempotency - yeniden deneme mantığının neden böyle göründüğü.
- Komut satırından URL kısaltıcı - aynı çağrılar, yeniden kullanılabilir bir betik olarak.
- 301 ve 302 yönlendirmeleri - hareketli bir bağlantının neden geçici yönlendirmeye ihtiyaç duyduğu.
- Sentry ve Datadog ile bağlantı yönlendirmelerini izleme - pipeline yeşile döndükten sonra bozuk bir hedefi yakalamak.
- GitHub Actions ile kısa bağlantılar - sırlar ve eşzamanlılıkla birlikte GitHub karşılığı.
Sıkça sorulan sorular
GitLab CI kısa bağlantı oluşturabilir mi?
Evet. curl çalıştırabilen her iş, bir URL kısaltıcının REST API'sini çağırabilir; dolayısıyla bir GitLab CI işi kısa bağlantı oluşturabilir, hedefini güncelleyebilir ya da devre dışı bırakabilir. API anahtarı maskeli bir CI/CD değişkeninde durur ve iş onu Bearer belirteci olarak gönderir. Bunun için yerel bir GitLab entegrasyonuna gerek yok.
Bir API anahtarını GitLab CI'da güvenle nasıl saklarım?
Settings, CI/CD, Variables altında görünürlüğü Masked and hidden olarak ekleyin; yalnızca korumalı dallar ya da etiketler okuyacaksa Protect variable kutusunu işaretleyin. Maskeleme değeri iş günlüklerinden uzak tutar, ancak GitLab'ın kendi dokümanları bunun garantili bir savunma olmadığını söyler; bu yüzden anahtarın kendisini ihtiyaç duyduğu en az yetkiyle sınırlayın.
Korumalı değişkenim merge request pipeline'ında neden boş geliyor?
Korumalı değişkenler yalnızca korumalı dallarda ya da korumalı etiketlerde çalışan pipeline'lara iletilir. Bir özellik dalından gelen merge request pipeline'ı varsayılan olarak buna uymaz, bu yüzden değişken boş gelir. İnceleme işleri için ayrı, daha düşük yetkili korumasız bir anahtar kullanın ya da korumalı anahtarı yalnızca etiket pipeline'larına ayırın.
Her GitLab review app'ine nasıl kısa bağlantı veririm?
Merge request pipeline'larında, proje adı ve CI_MERGE_REQUEST_IID ile oluşturulmuş bir slug'ı review app adresine yönlendirerek upsert eden bir iş çalıştırın. Ortaya çıkan kısa URL'yi bir dotenv raporuna yazın ve environment:url olarak kullanın; böylece merge request bileşeni doğrudan ona bağlanır. Bir stop işi, ortam durduğunda bağlantıyı devre dışı bırakır.
Son sürüm kısa bağlantısı için 301 mi 302 mi kullanılmalı?
302 kullanın. Bir latest bağlantısı her sürümde hedef değiştirir ve 301, tarayıcılara ve önbelleklere taşınmanın kalıcı olduğunu söyler; bu yüzden bazı istemciler insanları eski sürüme göndermeye devam eder. redirect_status ayarlamadığınızda Elido yeni bağlantılar için varsayılan olarak 302 kullanır ve burada doğru seçim budur.
Elido için yerel bir GitLab entegrasyonu var mı?
Henüz yok. Yerel bir GitLab entegrasyonu yolda ve GitLab entegrasyon sayfasından bekleme listesine katılabilirsiniz. Bu rehberdeki her şey bugün bir pipeline işinden genel REST API üzerinden çalışır; GitLab tarafında bir CI/CD değişkeni dışında kurulacak hiçbir şey yoktur.
Elido'yu deneyin
Bir URL yapıştırın, çalışan bir kısa bağlantı alın
Kayıt gerekmez. Bağlantı 30 gün boyunca yaşar. Sonsuza kadar saklamak için kaydolun.
Kayıt gerekmez. Ücretsiz kaydolun, ayda 50 bağlantı oluşturun.