Bir GitHub Actions URL kısaltıcı adımı birkaç satır kabuk komutudur: şifreli bir gizli anahtardan API anahtarını okuyun, slug'ın zaten var olup olmadığına bakın, sonra ya hedefini güncelleyin ya da oluşturun. Her push'ta çalıştırın; aynı kısa bağlantı her zaman en yeni önizlemeye, dokümantasyon derlemesine ya da yapıta işaret eder. Pazar yeri eylemi gerekmez. curl ve jq, GitHub tarafından barındırılan her Ubuntu çalıştırıcısında hazır gelir.
Cevabın tamamı bu; yazının geri kalanı, bir iki yüz iş akışı çalıştırması boyunca ayakta kalmasını sağlayan kısım. GitHub Actions'ta kısa bağlantının nasıl oluşturulacağını arayanlar genellikle tek bir POST isteğine kadar gelir ve aynı çekme isteğine ikinci push'a kadar işe yarar; o zaman oluşturma çağrısı bir çakışma döndürür ve iş kırmızıya döner. Çözüm, adımı bir oluşturma değil, bir upsert olarak ele almaktır. Ters giden diğer şey anahtarın kendisidir; genellikle bir CI işinin ihtiyacından çok daha fazla erişimi olan birinin kişisel belirtecidir.
Bağlantıları zaten kod olarak yönetiyorsanız, Terraform olarak kısa bağlantılar aynı fikrin bildirimsel sürümüdür ve insan takvimine göre değişen bağlantılar için daha iyi uyar. Hedef yalnızca bir derleme bittiğinde var olduğunda ise iş akışı adımı kazanır.
Bir GitHub Actions URL Kısaltıcı Adımı Nasıl Çalışır
Her çalıştırma, https://api.elido.app/v1 adresindeki REST API'ye karşı aynı üç şeyi yapar. Çalışma alanının bağlantılarını slug'a göre süzerek listeler. Bulduğu bağlantıya bir PATCH, hiçbir şey bulamadıysa bir POST gönderir. Sonraki adım kullanabilsin diye kısa URL'yi $GITHUB_OUTPUT içine yazar.
Neden kısaltıcının rastgele bir slug üretmesine izin vermiyoruz? Çünkü o zaman bağlantıyı bir daha bulamazsınız. Slug, iş akışının her çalıştırmada zaten bildiği bir şeyden gelmeli: çekme isteği numarası, dal adı, latest gibi sabit bir sözcük. Kararlı bir slug kararlı bir kısa URL demektir ve bu, onu yer imlerine ekleyen gözden geçirenler ya da bir bilete yapıştıran ürün yöneticileri için bütün değerdir.
API Anahtarını Şifreli Bir Gizli Anahtar Olarak Saklama
Anahtarı panoda oluşturun ve hemen kopyalayın, çünkü yalnızca bir kez gösterilir (elido_ ile başlar), sonra Settings, ardından Secrets and variables, ardından Actions altında ELIDO_API_KEY olarak kaydedin. GitHub'ın GitHub Actions'ta gizli anahtar kullanma rehberi depo ve ortam düzeylerini, ayrıca kuruluş gizli anahtarlarını kapsar. Dağıtım yapan her şey için onu, gerekli gözden geçirenleri olan bir ortama koyardım. O zaman başıboş bir dal onu kullanamaz.
Üç değer gizli değil: ELIDO_WORKSPACE_ID, ELIDO_DOMAIN_ID ve ELIDO_HOST. Bunlar, sonradan geri okuyabileceğiniz yapılandırma değişkenlerine aittir ve üçü arasında önce doğru alınması gereken alan adı kimliğidir, çünkü oluşturma çağrısı onu ister. Her alan adının id ve hostname değerlerini döndüren GET /v1/workspaces/{workspace_id}/domains ile bir kez arayabilirsiniz.
Gizli anahtarı tüm işe değil, API'yi çağıran tek adıma eşleyin. Adım düzeyinde bir env, onu işin başlattığı diğer her süreçten, yazmadığınız üçüncü taraf eylemler dahil, uzak tutar. Dar tutun.
Her Çekme İsteğinde Bir URL Kısaltan Çalışan Bir İş Akışı
Bu, bir GitHub iş akışında URL kısaltmanın en yaygın nedeni olan, çekme isteği başına bir önizleme bağlantısı için tam dosyadır. .github/workflows/preview-link.yml içine bırakın ve DEST satırını önizleme dağıtımlarınızın indiği yere göre değiştirin.
name: Preview short link
on:
pull_request:
types: [opened, reopened, synchronize]
permissions:
contents: read
pull-requests: write
concurrency:
group: preview-link-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
short-link:
# Forks get no secrets; skip them instead of failing.
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
env:
API: https://api.elido.app/v1/workspaces/${{ vars.ELIDO_WORKSPACE_ID }}
DOMAIN_ID: ${{ vars.ELIDO_DOMAIN_ID }}
HOST: ${{ vars.ELIDO_HOST }}
SLUG: pr-${{ github.event.pull_request.number }}-myapp
DEST: https://pr-${{ github.event.pull_request.number }}.preview.example.com
steps:
- name: Create or update the short link
id: link
env:
ELIDO_API_KEY: ${{ secrets.ELIDO_API_KEY }}
run: |
set -euo pipefail
auth=(-H "Authorization: Bearer $ELIDO_API_KEY" -H "Content-Type: application/json")
# 1. Find an existing link with exactly this slug on this domain.
link_id=$(curl -sS --fail-with-body "${auth[@]}" "$API/links?q=$SLUG&limit=100" \
| jq -r --arg s "$SLUG" --argjson d "$DOMAIN_ID" \
'.items[] | select(.slug == $s and .domain_id == $d) | .id' | head -n1)
if [ -n "$link_id" ]; then
# 2a. Found: point it at the new destination.
curl -sS --fail-with-body -X PATCH "${auth[@]}" "$API/links/$link_id" \
-d "$(jq -n --arg u "$DEST" '{destination_url: $u, status: "active"}')" > /dev/null
else
# 2b. Not found: create it. The key makes curl's retries safe.
curl -sS --fail-with-body --retry 3 -X POST "${auth[@]}" "$API/links" \
-H "Idempotency-Key: $GITHUB_REPOSITORY-$SLUG-$GITHUB_RUN_ID" \
-d "$(jq -n --arg u "$DEST" --arg s "$SLUG" --argjson d "$DOMAIN_ID" \
'{domain_id: $d, slug: $s, destination_url: $u, tags: ["ci", "preview"]}')" > /dev/null
fi
echo "url=https://$HOST/$SLUG" >> "$GITHUB_OUTPUT"
- name: Comment once, when the pull request opens
if: github.event.action == 'opened'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh pr comment "${{ github.event.pull_request.number }}" \
--repo "${{ github.repository }}" \
--body "Preview: ${{ steps.link.outputs.url }}"
Birkaç satır yorum hak ediyor. --fail-with-body, bir 4xx ya da 5xx'i hata gövdesini yazdırmaya devam ederken başarısız bir adıma çevirir; düz curl -s bunu yapmaz, 401'de 0 ile çıkar ve iş keyifle devam eder. İstek gövdeleri dize enterpolasyonu yerine jq -n ile kurulur; böylece tırnak ya da ve işareti içeren bir hedef JSON'u bozamaz. Yorum adımı da yalnızca opened olduğunda çalışır. Kısa URL hiç değişmediği için tek bir yorum çekme isteğinin ömrü boyunca doğru kalır ve kimse her push'ta bildirim almaz.
concurrency bloğu süs değil. İki hızlı push, aksi halde ikisi de "henüz bağlantı yok" gören ve ikisi de bir tane oluşturmaya çalışan iki çalıştırma başlatırdı. GitHub'ın iş akışı eşzamanlılığını denetleme belgeleri gruplamayı açıklar; burada eski çalıştırma iptal edilir ve yarış hiç yaşanmaz.
İdempotentlik: Kısa Bağlantıyı Güncelleyin, Yinelemeyin
İdempotent sözcüğünün altında iki farklı başarısızlık saklanır ve iş akışı onları ayrı ele alır. Birincisi yeniden çalıştırmadır: ikinci bir push, elle "Re-run jobs", yeniden açılan bir çekme isteği. Ara-sonra-PATCH dalı bunun içindir. İkincisi yeniden denenen istektir: curl POST'u gönderir, yanıt gelmeden ağ kopar ve curl onu yeniden gönderir. Idempotency-Key başlığı bunu kapsar. Elido ilk başarılı yanıtı anahtara karşılık 24 saat saklar ve eşleşen bir yeniden deneme için tekrar oynatır; böylece oluşturma bir kez çalışır. Tam mekanikler hız sınırları, yeniden denemeler ve idempotentlik yazısında.
Slug çakışmaları, insanların gözden kaçırdığı kısımdır. Slug'lar çalışma alanı başına değil, yönlendirme alan adı başına benzersizdir. Paylaşılan bir alan adında diğer her Elido müşterisi aynı ad alanındadır ve pr-12 kadar sade bir slug büyük olasılıkla birinin eline geçmiştir. Arama onların bağlantısını görmez (yalnızca sizin çalışma alanınızı listeler), bu yüzden POST gider ve 409 slug already exists for this domain ile döner. İki çözüm: slug'a bir proje sözcüğü ekleyin ya da CI bağlantılarını ad alanının yalnızca size ait olduğu kendi özel alan adınıza koyun. İkisini de yapardım.
Depo adının slug'ın başında değil sonunda durmasının ikinci, daha sinsi bir nedeni var. q parametresi, slug, hedef ve başlık üzerinde bir alt dize eşleşmesidir. myapp-pr-1 ile arama myapp-pr-10 ile myapp-pr-199 arasını da döndürür; bu, tek bir sayfanın döndürdüğü 100 sonuçtan fazladır ve istediğiniz tek bağlantı, en eski olduğu için sondan düşer. pr-1-myapp kendisi dışında hiçbir şeyle eşleşmez. Küçük bir ayrıntı ve fark etmem, "PR #1 neden hep 409 alıyor" diye utanç verici ölçüde uzun bir öğleden sonra sürdü.
Otomatikleştirmeye Değer Üç CI Kısa Bağlantı İşi
Önizleme iş akışı bir örüntüdür. Tetikleyiciyi, slug'ı ve hedefi değiştirin; aynı adım, ekiplerin gerçekte otomatikleştirdiklerinin çoğunu kapsar. (Sürüm notları kendi başına bir konu; sürüm notlarında bağlantı kısaltma yazısında ele alındı.)
| Kullanım durumu | Tetikleyici | Slug | Adımın yaptığı |
|---|---|---|---|
| Çekme isteği başına önizleme dağıtımı | pull_request | pr-42-myapp | Her push'ta upsert, kapanışta sil |
| Dokümantasyon dağıtımı | main dalına push | docs-myapp | Yeni dağıtılan dokümantasyon URL'sine PATCH |
| En son derleme | main dalına push ya da etiket | latest-myapp | Saklanan bağlantı kimliğine PATCH, arama yok |
| Gecelik yapıt | schedule | nightly-myapp | En yeni yapıt URL'sine PATCH |
En son derleme durumu bunların en basiti. Bağlantıyı bir kez elle oluşturun, sayısal kimliğini bir değişken olarak kaydedin ve iş tek bir çağrıya iner:
- name: Point the latest link at this build
env:
ELIDO_API_KEY: ${{ secrets.ELIDO_API_KEY }}
API: https://api.elido.app/v1/workspaces/${{ vars.ELIDO_WORKSPACE_ID }}
DEST: https://builds.example.com/${{ github.sha }}/
run: |
curl -sS --fail-with-body -X PATCH \
-H "Authorization: Bearer $ELIDO_API_KEY" -H "Content-Type: application/json" \
"$API/links/${{ vars.ELIDO_LATEST_LINK_ID }}" \
-d "$(jq -n --arg u "$DEST" '{destination_url: $u}')"
Bu hareketli bağlantıları, redirect_status ayarlamadığınızda varsayılan olan 302'de tutun. Bir 301 tarayıcılara yanıtı önbelleğe alabileceklerini söyler ve dün tıklayanlar dünkü derlemeye düşmeye devam eder; 301 ve 302 yönlendirmeleri yazımızda uzun hali var.
Önizleme bağlantıları için çekme isteği kapandığında temizlik yapın. Tetikleyici türlerine closed ekleyin, aramayı yeniden kullanın ve DELETE /v1/workspaces/{workspace_id}/links/{link_id} gönderin. Silinen bir slug yeniden kullanıma serbesttir. Tıklama geçmişini saklamak isterseniz bunun yerine {"status": "disabled"} ile PATCH yapın; yukarıdaki upsert her çalıştırmada status: "active" ayarlar, bu yüzden yeniden açılan bir çekme isteği bağlantısını geri getirir.
Tek bir depoda denemeye hazır mısınız? Ücretsiz bir çalışma alanı başlatın, bir anahtar oluşturun; üç değişken ayarlandığında yukarıdaki iş akışı yazıldığı gibi çalışır.
CI İçin En Az Yetkili API Anahtarları
Bir CI gizli anahtarındaki anahtar, iş akışının yaptığını yapabilmeli, daha fazlasını değil. Kişisel anahtarların çalışma biçimi yüzünden bu göründüğünden zordur.
Kişisel bir API anahtarı, onu oluşturan kişi olarak kimlik doğrular. O kişinin yapabildiği her şeyi anahtar da yapabilir ve kişi şirketten ayrıldığında anahtar hesabıyla birlikte gider. CI için bunun yerine bir makine kullanıcısı kullanırdım: tek bir çalışma alanına ait, kendi rolü olan ve belirteçlerini yalnızca oturum açmış bir insan yöneticinin üretebildiği ya da iptal edebildiği bir hizmet hesabı. Panoda Machine users altında, bağlantı oluşturabilen, düzenleyebilen ve silebilen en düşük yerleşik rol olan editör rolüyle oluşturun, sonra ona bir son kullanma tarihiyle bir belirteç üretin. Makine kullanıcısını devre dışı bırakmak tuttuğu her belirteci bir anda öldürür; bu, bir gizli anahtarın sızdığı gün tam olarak istediğiniz düğmedir.
Maliyeti olmayan dört alışkanlık daha:
- Depo başına bir belirteç, depo adıyla adlandırılmış; böylece denetim izi hangi deponun hangi bağlantıyı oluşturduğunu söyler.
- İnsanların güvendiği bir bağlantıyı değiştiren her iş akışı için gerekli gözden geçirenlerle ortam gizli anahtarları.
- Örnekteki gibi iş akışının en üstünde açıkça ayarlanmış
permissions:; böyleceGITHUB_TOKENyalnızca işin ihtiyaç duyduğunu alır. - Fork çekme isteklerinden gizli anahtara ulaşmak için asla
pull_request_targetkullanmayın. GitHub Security Lab'ın pwn isteklerini önleme yazısı, güvenilmeyen kodu bir yazma belirtecinin yanında çalıştırmanın neden kötü bittiğini gösterir.
Çalışma alanları API erişimini IP izin listesiyle de kısıtlayabilir. Sabit çıkışlı kendi sunucudaki çalıştırıcılar için güçlü bir denetimdir, adresleri çok büyük ve değişken bir havuzdan gelen GitHub tarafından barındırılan çalıştırıcılar için neredeyse işe yaramaz. İş akışlarınız üretime dokunuyorsa GitHub'ın kendi güvenli kullanım başvurusu bir saate değer.
Pratikte Ne Bozulur
Çoğu başarısızlık dört yerden gelir ve --fail-with-body açıksa her biri okunabilir bir hata olarak görünür. Her çağrıda 404 genellikle çalışma alanı kimliği değişkeninin yanlış olduğu ya da anahtarın farklı bir çalışma alanına ait olduğu anlamına gelir. domain_id is required diyen bir 400, değişkenin boş olduğu anlamına gelir; tipik olarak işin kullandığından farklı bir ortamda ayarlandığı için. 409, idempotentlik bölümündeki paylaşılan ad alanı çakışmasıdır. 429 ise anahtar başına hız sınırını aştığınız anlamına gelir; çalıştırma başına tek bir upsert buna takılmaz ama elli işlik bir matris takılabilir.
Bir şey hiç hata değil. Bir PATCH'ten sonra bir ziyaretçi bir süre eski hedefe ulaşabilir, çünkü yönlendirmeler hızlı kalmaları için ziyaretçiye yakın önbelleğe alınır. Güncellemeden hemen sonra yeni hedefi doğrulayan bir duman testi kararsız olur. Kısa bir geri çekilmeyle yoklayın ya da bunun yerine API yanıtına karşı doğrulayın.
Adımın dışarıya rapor vermesini istiyorsanız, bir bağlantı değiştiğinde tetiklenen bağlantı olayları için webhook'lar ile eşleştirin ya da iş akışını commit etmeden önce yerel test için CLI rehberindeki curl ve jq örüntülerini kullanın. API ve SDK başvurusu bağlantı uç noktalarının kabul ettiği her alanı listeler.
Temel yazıyı okuyun → Kısa bağlantılarınızı Terraform olarak yönetin
Blogda İlgili Yazılar
- URL kısaltıcı API: hız sınırları, yeniden denemeler ve idempotentlik - bu iş akışının dayandığı yeniden deneme güvenliği kuralları.
- URL kısaltıcı CLI - aynı curl ve jq çağrıları, terminalinizden.
- Ücretsiz URL kısaltıcı API - curl, JavaScript, Python ve Go'da oluşturma çağrısı.
- Geliştiriciler için URL kısaltıcılar - konuşmalarda, README'lerde ve açık kaynak projelerinde kısa bağlantılar.
- Bağlantı olayları için webhook'lar - bir CI işi bir bağlantıyı değiştirdiğinde tepki verin.
- GitLab CI kısa bağlantıları - aynı upsert örüntüsü, bir .gitlab-ci.yml işi olarak.
Sıkça sorulan sorular
GitHub Actions kısa bağlantı oluşturabilir mi?
Evet. Bir iş akışı adımı, GitHub tarafından barındırılan çalıştırıcılarda jq ile birlikte hazır gelen curl ile herhangi bir kısaltıcının REST API'sini çağırabilir. Adım API anahtarını şifreli bir gizli anahtardan okur, hedef URL'yi gönderir ve sonuçtaki kısa URL'yi bir adım çıktısına yazar; böylece sonraki adımlar onu bir çekme isteği yorumunda ya da iş özetinde paylaşabilir.
GitHub Actions'ta bir URL kısaltıcı API anahtarını nasıl saklarım?
Şifreli bir depo ya da ortam gizli anahtarı olarak kaydedin, sonra ifade sözdizimi içinde ELIDO_API_KEY: secrets.ELIDO_API_KEY gibi bir env girdisiyle yalnızca ona ihtiyaç duyan tek adıma eşleyin. GitHub değeri günlüklerde maskeler. Çalışma alanı kimliği ve alan adı kimliği gibi gizli olmayan değerleri okunabilir kalsınlar diye yapılandırma değişkenlerinde tutun.
Her iş akışı çalıştırmasında yinelenen kısa bağlantılar oluşturmaktan nasıl kaçınırım?
Adımı bir upsert yapın. Slug'ı çekme isteği numarası gibi kararlı bir şeyden türetin, önce arayın ve zaten varsa hedefi değiştirmek için bir PATCH gönderin. Yalnızca arama boş döndüğünde oluşturun. Oluşturma çağrısındaki bir Idempotency-Key başlığı, ağ zaman aşımından sonra yeniden denenen isteğin ayrı durumunu kapsar.
İş akışım kısa bağlantı oluştururken neden 409 alıyor?
Slug o alan adında zaten alınmış. Elido'da slug'lar yönlendirme alan adı başına benzersizdir ve paylaşılan bir alan adı diğer tüm çalışma alanlarıyla paylaşılır; bu yüzden pr-12 gibi genel bir slug büyük olasılıkla zaten vardır. Slug'a bir proje öneki ya da soneki ekleyin ya da tüm ad alanının size ait olduğu kendi özel alan adınızı kullanın.
Kısa bağlantı adımları fork'lardan gelen çekme isteklerinde çalışır mı?
Düz pull_request tetikleyicisiyle hayır, çünkü GitHub, bir fork'un başlattığı iş akışlarına depo gizli anahtarlarını geçirmez. İşi, baş depo üzerindeki bir if koşuluyla fork'lar için atlayın. Gizli anahtarı almak için pull_request_target'a geçmek risklidir, çünkü incelemediğiniz kodun yanında yazma erişimiyle çalışır.
En son derlemeye işaret eden bir bağlantı 301 mi 302 yönlendirme mi kullanmalı?
302 ya da 307 kullanın. Tarayıcılar bir 301'i süresiz önbelleğe alabilir; bu yüzden iş akışınız bağlantıyı taşıdıktan sonra geri dönen ziyaretçiler eski bir derlemeye düşmeye devam eder. Elido bağlantıları redirect_status ayarlamadığınızda varsayılan olarak 302 kullanır; bu, hedefini bir hattın değiştirdiği her bağlantı için doğru seçimdir.
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.