after_script не видит export и cd: передаём состояние файлом
В script вычислили каталог отчёта, экспортировали REPORT_DIR и перешли в него. В after_script переменная пуста, а относительный путь указывает в корень проекта. Это ожидаемая граница исполнения GitLab Runner: after_script выполняется в новой оболочке. Экспорт внутри script не изменяет окружение следующей оболочки, а cd не сохраняет её рабочий каталог.
При этом файлы внутри рабочего дерева доступны следующей фазе. Небольшое несекретное состояние можно сохранить в файл и прочитать по явному пути. Так передаётся конкретное значение, а не надежда на продолжение прежней интерактивной сессии.
Воспроизведём передачу без внешних действий
Пример записывает идентификатор отчёта в .job-state, затем after_script создаёт итоговую заметку. Она попадёт в артефакты, поскольку after_script выполняется до их загрузки.
report-state:
image: alpine:3.22
script:
- mkdir -p out
- printf '%s\n' "$CI_JOB_ID" > .job-state
- export REPORT_ID="$CI_JOB_ID"
- cd out
- printf '%s\n' done > result.txt
after_script:
- |
cd "$CI_PROJECT_DIR" || exit 1
if [ -f .job-state ]; then
IFS= read -r report_id < .job-state
printf 'report=%s\n' "$report_id" > out/summary.txt
fi
artifacts:
when: always
paths: [out/]
В артефакте должны оказаться result.txt и summary.txt. Во втором записан реальный CI_JOB_ID текущей job. Переменная REPORT_ID для передачи не используется: она оставлена в script, чтобы было видно, что экспорт и сохранённый файл имеют разные роли.
Файл читается как строка данных, а не через source. Если в состоянии хранится произвольное внешнее значение, подключать его как shell-код нельзя. Для нескольких полей выберите определённый формат, например JSON, и парсер, доступный в образе job.
after_script не меняет успешность script
Если основная часть прошла успешно, ошибка after_script обычно не превращает job в красную. Поэтому проверку, от которой зависит допуск к выпуску, размещайте в script или отдельной проверяющей job. after_script подходит для дополнительной диагностики и очистки, чей отказ не должен подменять результат основной работы.
В примере summary — вспомогательная заметка. Если она обязательна для следующего шага, её создание следует перенести в script и проверить до завершения. Иначе pipeline может стать зелёным без нужного файла, а ошибка проявится только в потребителе.
after_script имеет отдельный timeout и не является гарантированным finally для любого способа окончания job. Для общего timeout и некоторых инфраструктурных отказов действуют ограничения. Долговременную очистку внешних ресурсов нельзя строить только на предположении, что эта фаза всегда выполнится.
Если один runner переиспользует рабочий каталог, не полагайтесь на отсутствие старого файла. В начале script удалите или заново создайте только свой файл состояния, а в записанном значении сохраните идентификатор текущей job. Тогда after_script сможет отличить свежий результат от оставшегося после прерванной попытки.
Ограничьте передаваемое состояние
Храните лишь то, что нужно следующей фазе, и размещайте файл в CI_PROJECT_DIR. Изменения за пределами рабочего дерева могут зависеть от executor и не сохраняться так, как вы ожидаете. Полный env сохранять не надо: в нём могут быть секреты, а большинство значений воспроизводится штатными переменными CI.
Проверьте job с обычным успехом script и с намеренным отказом после записи .job-state. Затем отдельно проверьте сценарий, когда основная часть падает до создания файла: after_script должен корректно пережить его отсутствие и не генерировать ложный summary из старого результата.
В курсе GitLab CI/CD есть жизненный цикл jobs, артефакты и диагностика. Откройте программу и продолжите к pipeline, где обязательные проверки, вспомогательные отчёты и очистка размещены в подходящих фазах и не зависят от скрытого состояния shell.
Ещё по теме
Продолжить на практике
- GitLab CI/CD: автоматизация сборки и деплоя ↗
От первого .gitlab-ci.yml до pipeline, который тестирует код, собирает образ и выкладывает приложение. Runners, artifacts, cache, registry, окружения и безопасный откат — на одном практическом проекте.
