GitHub Action¶
Используйте indexnow как шаг в любом workflow GitHub Actions. Action скачивает релизный бинарь под OS/arch раннера, сверяет sha256 с checksums.txt из того же релиза и запускает indexnow submit с переданными inputs.
- uses: jtprogru/indexnow@v0
with:
key: ${{ secrets.INDEXNOW_KEY }}
sitemap: https://example.com/sitemap.xml
Пинуйте на мажор (@v0) для floating-but-stable, на тег (@v0.5.0) для точности, на SHA коммита — для параноидального supply-chain режима.
Поддерживаемые раннеры¶
runs-on |
Статус |
|---|---|
ubuntu-latest, ubuntu-* (x64, arm64) |
поддерживается |
macos-latest, macos-* (x64, arm64) |
поддерживается |
windows-* |
не поддерживается — preflight падает с подсказкой про ubuntu/macos |
Inputs¶
| Имя | Обязательность | Default | Заметки |
|---|---|---|---|
key |
да | — | Ключ IndexNow (8..128, [A-Za-z0-9-]). Идёт через env, не флаги. |
urls |
один из | — | URL'ы через перевод строки. |
file |
один из | — | Путь к файлу (по одному URL на строку). |
sitemap |
один из | — | URL или локальный путь до sitemap.xml (.gz и <sitemapindex> раскрываются). |
urls-from |
один из | — | Bash-сниппет, чей stdout трактуется как список URL'ов. См. Кастомные источники URL. |
sitemap-since |
нет | — | RFC3339; записи со старее <lastmod> отбрасываются. |
sitemap-timeout |
нет | дефолт CLI (30s) |
Per-request HTTP timeout для sitemap. |
host |
нет | вывод из первого URL | Хост сайта (например example.com). |
key-location |
нет | derive из host + key |
Абсолютный URL hosted-key файла. |
endpoint |
нет | api |
Алиас или полный URL; comma-separated для fan-out. |
user-agent |
нет | indexnow/<version> |
Заголовок User-Agent. |
config |
нет | — | Путь (относительно $GITHUB_WORKSPACE) к yaml-конфигу indexnow — defaults для host, key, endpoint и т.д. |
fail-on |
нет | any |
any\|4xx\|5xx\|never — какие классы ответа дают exit ≠ 0. |
quiet |
нет | false |
Глушит stdout CLI в логе шага. |
verbose |
нет | false |
slog lifecycle/retry в stderr. |
dry-run |
нет | false |
Печатает план и выходит, не идёт по сети. |
max-retries |
нет | дефолт CLI | Ретраи на 429/5xx/transport. |
base-backoff |
нет | дефолт CLI | Начальный backoff (Go duration, например 200ms). |
max-backoff |
нет | дефолт CLI | Кап backoff'а. |
version |
нет | тег action'а | Какой релиз indexnow ставить. "latest" резолвится в рантайме. |
github-token |
нет | ${{ github.token }} |
Используется только для GitHub Releases API. |
Ровно один из urls / file / sitemap / urls-from должен быть задан — иначе preflight падает.
Outputs¶
| Имя | Заметки |
|---|---|
exit-code |
Exit-код indexnow submit. |
submitted-count |
Сумма urlCount по всем батчам. 0 в dry-run. |
failed-count |
Батчи с не-2xx или ошибкой. 0 в dry-run. |
report |
Одной строкой; также пишется в $GITHUB_STEP_SUMMARY. |
Рецепты¶
На каждый push в content/¶
name: indexnow
on:
push:
branches: [main]
paths: ["content/**"]
jobs:
notify:
runs-on: ubuntu-latest
steps:
- uses: jtprogru/indexnow@v0
with:
key: ${{ secrets.INDEXNOW_KEY }}
sitemap: https://example.com/sitemap.xml
sitemap-since: ${{ github.event.before }}
endpoint: bing,yandex
sitemap-since: ${{ github.event.before }} — строка, action прокидывает её в --sitemap-since (парсит RFC3339). Для push-event'ов это timestamp предыдущего HEAD: записи со старее <lastmod> пропускаются, остальное уходит.
Каждый час по расписанию¶
on:
schedule:
- cron: "0 * * * *"
jobs:
notify:
runs-on: ubuntu-latest
steps:
- uses: jtprogru/indexnow@v0
with:
key: ${{ secrets.INDEXNOW_KEY }}
sitemap: https://example.com/sitemap.xml
Не хочется возиться с арифметикой дат в YAML — просто не передавайте sitemap-since, и каждый запуск пересубмитит весь sitemap. IndexNow идемпотентен, цена — HTTP-вызов.
Кастомные источники URL через urls-from¶
Когда ни urls, ни file, ни sitemap не подходят — соберите список сами. urls-from — bash-сниппет, чей stdout становится списком URL'ов (один URL на строку, # в начале — комментарий, пустые строки игнорируются). Запускается в $GITHUB_WORKSPACE, так что git, локально-выкаченные файлы и другие инструменты доступны сразу.
Пустой вывод — успех: step выходит с submitted-count=0 и submit не вызывается. Non-zero exit вашего сниппета валит step (stderr пробрасывается в лог).
Рецепт: только изменённые URL'ы из git diff¶
Исходный мотив. Маппинг путь→URL — проектно-специфичный (Hugo permalinks, Eleventy permalink: в front-matter, кастомные роутеры), поэтому он живёт в вашем сниппете, а не в схеме конфига, которую indexnow вынужден тащить годами.
- uses: actions/checkout@v6
with:
fetch-depth: 0 # нужно, чтобы `git diff <base>..HEAD` резолвился
- uses: jtprogru/indexnow@v0
with:
key: ${{ secrets.INDEXNOW_KEY }}
host: example.com
urls-from: |
git diff --name-only --diff-filter=AMR \
"${{ github.event.before }}..${{ github.event.after }}" -- 'content/**/*.md' |
sed 's#^content/\(.*\)\.md$#https://example.com/\1/#'
Краевой случай: force-push в новую ветку даёт github.event.before = 0000000… — оберните в if: и фоллбекните на origin/main..HEAD.
Рецепт: sitemap с content-фильтром¶
Когда --sitemap-since недостаточно избирателен — например, нужны только URL'ы под определённым префиксом:
- uses: jtprogru/indexnow@v0
with:
key: ${{ secrets.INDEXNOW_KEY }}
urls-from: |
curl -sSL https://example.com/sitemap.xml |
grep -oE '<loc>[^<]+</loc>' |
sed -E 's#</?loc>##g' |
grep '^https://example.com/blog/'
Рецепт: URL'ы из CMS API¶
- uses: jtprogru/indexnow@v0
with:
key: ${{ secrets.INDEXNOW_KEY }}
urls-from: |
curl -sSL -H "Authorization: Bearer ${{ secrets.CMS_TOKEN }}" \
https://cms.example.com/api/recently-published |
jq -r '.items[].url'
urls-from — фича только Action'а. В CLI эквивалент — обычный shell-pipe в indexnow submit --stdin:
git diff --name-only HEAD~1..HEAD -- 'content/**/*.md' |
sed 's#^content/\(.*\)\.md$#https://example.com/\1/#' |
indexnow submit --stdin
Секреты¶
INDEXNOW_KEY кладите в repository или org-level secrets. Action берёт его как input и передаёт через env (INDEXNOW_KEY) — значение никогда не появляется в трасе command-line, даже с set -x.
Hosted key-файл: положите <key>.txt в корень static-сайта с содержимым, равным ключу. CLI-сабкоманд verify это проверяет; пока не выведен в input action'а — позовите indexnow verify следующим шагом, если нужно подтверждение в CI.
Как устроена установка¶
На первом использовании в job:
- Резолв версии (
inputs.version→ тег action'а →latest). - Скачивается
indexnow_{Linux|Darwin}_{x86_64|arm64}.tar.gzиchecksums.txt. - Sha256-проверка (
sha256sum -cна Linux,shasum -a 256на macOS). - Распаковка в
$RUNNER_TOOL_CACHE/indexnow/<version>/<os-arch>/. - Каталог кэшируется через
actions/cacheс ключом version+os+arch — последующие jobs (и reruns) пропускают скачивание.
checksums.txt.sig (GPG-подпись) — для out-of-band паранои; сам action полагается на TLS GitHub Releases + sha256.