Using Gitlab-CI externals to get feedback for EAS

Hello,

I’ve built a full setup with gitlab-ci that works. My .gitlab-ci.yml contains a job to run eas build, which is waiting the whole time for its completion, using CI minutes. Then it runs another job running eas submit, which is also waiting the whole time, using more CI minutes.

To avoid using a lot of CI minutes from gitlab, I should run eas build --no-wait --auto-submit. But then, I won’t have any feedback in my CI pipeline telling me what’s going on in EAS.

For sure there’s a better way, and I tried making a PoC for that, but with limitations.

I could use a gitlab API, that enables to post a build status to a commit:

The only lifecycle scripts I can run today are, according to the doc, in package.json:

    "eas-build-pre-install": "bash contrib/eas-build-pre-install.sh",
    "eas-build-post-install": "bash contrib/eas-build-post-install.sh",
    "eas-build-pre-upload-artifacts": "bash contrib/eas-build-pre-upload-artifacts.sh",

and I can add one before it runs on eas:

    "prebuild:eas": "bash contrib/prebuild-eas.sh production",
    "build:eas": "eas build --no-wait"

That way, I can build the following lifecycle:

  • contrib/prebuild-eas.sh production
curl --request POST \
     --header "PRIVATE-TOKEN: ${CI_TOKEN}" \
     -d "ref=${CI_COMMIT_REF_NAME}" \
     -d "pipeline_id=${CI_PIPELINE_ID}" \
     -d "state=pending" \
     -d "name=EAS Build: ${1} / Android" \
     -d "description=The Expo application build is pending on EAS" \
     "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/statuses/${CI_COMMIT_SHA}"
  • contrib/eas-build-pre-install.sh
curl --request POST \
     --header "PRIVATE-TOKEN: ${CI_TOKEN}" \
     -d "?ref=${CI_COMMIT_REF_NAME}" \
     -d "&pipeline_id=${CI_PIPELINE_ID}" \
     -d "&state=running" \
     -d "&name=EAS Build: ${EAS_BUILD_PROFILE}" \
     -d "&description=The Expo application is building on EAS" \
     -d "&target_url=https://expo.dev/accounts/HARDCODED_ACCOUNT/projects/HARDCODED_PROJECT/builds/${EAS_BUILD_ID}" \
     "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/statuses/${CI_COMMIT_SHA}"
  • contrib/eas-build-pre-upload-artifacts
curl --request POST \
     --header "PRIVATE-TOKEN: ${CI_TOKEN}" \
     -d "?ref=${CI_COMMIT_REF_NAME}" \
     -d "&pipeline_id=${CI_PIPELINE_ID}" \
     -d "&state=running" \
     -d "&name=EAS Build: ${EAS_BUILD_PROFILE}" \
     -d "&description=The Expo application is building on EAS" \
     -d "&target_url=https://expo.dev/accounts/HARCODED_ACCOUNT/projects/HARCODED_PROJECT/builds/${EAS_BUILD_ID}" \
     "https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/statuses/${CI_COMMIT_SHA}"

though, to make the second and third script work, I need to pass the bunch of gitlab variables through to EAS. Because unlike app.json that you can transform into app.config.js, I need to dynamically update eas.json, but there’s no eas.config.js alternative, so I need to hack it using jq:

BUILD_ENV=$(cat << EOS
.build.production.env |= . + {
  "CI_COMMIT_SHA": "${CI_COMMIT_SHA}",
  "CI_COMMIT_REF_NAME": "${CI_COMMIT_REF_NAME}",
  "CI_PROJECT_ID": "${CI_PROJECT_ID}",
  "CI_JOB_TOKEN": "${CI_JOB_TOKEN}",
  "CI_PIPELINE_ID": "${CI_PIPELINE_ID}",
} | .cli |= . + { "requireCommit": false }
EOS
)

jq "${BUILD_ENV}" < eas.json > eas.tmp.json
mv eas.tmp.json eas.json

now it’s not perfect, there are issues:

  • on Gitlab side: the $CI_JOB_TOKEN cannot be used to update the build status, so I need to use a private token (set as $CI_TOKEN on both expo.dev secrets and gitlab variables), but I’m pretty sure there’s a way, I know other tools that make it work.

  • on EAS side:

    • there’s no way to determine whether it’s an iOS build or Android build (like there’s $EAS_BUILD_PROFILE to know the current profile), I could fix that by adding an env variable within .build.production.env.ios and .build.production.env.android
    • there’s no way to plug a script at the start/end of a submit action (something like eas-submit-before and eas-submit-after).

Also, injecting variables should be easier (using eas.config.js).

That’s a start :relaxed:

Once it’s all working, I got on my wishlist to:

  • follow the lifecycle of the submission
  • publish the artifacts links either on the pipeline or on the merge request ;
  • publish the app store/play store links (to validate the next steps) as an external job (to provide the link to finalize the publication)

To address the ‘there’s no way to determine whether it’s an iOS build or Android build’ point: perhaps the trackingContext or all of the metadata from the webhook payload can be made available in the environment at the time of the hooks.

Having hooks for submit would be a good extension to the webhooks that were already added before.

1 Like

Indeed, having a simple hooks system instead of webhooks would be ideal!

I don’t need/want to use webhooks to achieve that, as I don’t want to maintain a middleware that will just be a passthrough converting EAS webhook data into gitlab API 🤷

1 Like

I did make a feature request for this: