-
Notifications
You must be signed in to change notification settings - Fork 38
Replace REST cache with Azure Cache2 #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
23ac454
06f85f7
de9fb7e
0b35b86
8d67db3
ba6b5c2
4af4bd9
ecf875b
9d7da03
54067cc
697395c
5c28fdc
5fab10d
cde854a
d6f106b
4562202
e6e4396
65efed5
2a19e73
92b3af4
97086a6
cf93d3f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,7 @@ | ||
# Steps for publishing project cache | ||
|
||
steps: | ||
- bash: 'mkdir -p $(Build.StagingDirectory)' | ||
condition: and(succeeded(), eq(variables['Build.Reason'], 'IndividualCI')) | ||
displayName: '[Cache][Publish] Create cache directory' | ||
|
||
# continueOnError because on windows it has a permission denied error but the | ||
# export succeeds. | ||
- script: "esy export-dependencies" | ||
continueOnError: true | ||
condition: and(succeeded(), eq(variables['Build.Reason'], 'IndividualCI')) | ||
condition: eq(variables.CACHE_RESTORED, 'false') | ||
displayName: "esy export-dependencies" | ||
|
||
- bash: pwd && ls _export/* && mv _export '$(Build.StagingDirectory)' && ls '$(Build.StagingDirectory)/_export/' | ||
condition: and(succeeded(), eq(variables['Build.Reason'], 'IndividualCI')) | ||
displayName: '[Cache][Publish] move export to staging dir' | ||
|
||
# - bash: cd $ESY__CACHE_INSTALL_PATH && tar -czf $(Build.StagingDirectory)/esy-cache.tar . | ||
# workingDirectory: '' | ||
# condition: and(succeeded(), eq(variables['Build.Reason'], 'IndividualCI')) | ||
# displayName: '[Cache][Publish] Tar esy cache directory' | ||
|
||
# - bash: 'cd $(ESY__NPM_ROOT) && tar -czf $(Build.StagingDirectory)/npm-cache.tar .' | ||
# condition: and(succeeded(), eq(variables['Build.SourceBranch'], variables['System.PullRequest.TargetBranch'])) | ||
# displayName: '[Cache][Publish] Tar npm cache directory' | ||
|
||
- task: PublishBuildArtifacts@1 | ||
displayName: '[Cache][Publish] Upload tarball' | ||
condition: and(succeeded(), eq(variables['Build.Reason'], 'IndividualCI')) | ||
# TODO: The CI Build caches are pulled down by the last successful buildID | ||
# for the target branch. | ||
inputs: | ||
pathToPublish: '$(Build.StagingDirectory)' | ||
artifactName: 'cache-$(Agent.OS)-install' | ||
parallel: true | ||
parallelCount: 8 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,101 +1,68 @@ | ||
# Steps for restoring project cache | ||
|
||
# The cache key is built up of the following: | ||
# - We use a string that we can change to bust the cache | ||
# - The string "esy" | ||
# - The string for the OS | ||
# - The hash of the lock file | ||
steps: | ||
- bash: 'mkdir -p $(Build.StagingDirectory)' | ||
condition: and(eq(variables['Build.Reason'], 'PullRequest'), and(succeeded(), ne(variables['Build.SourceBranch'], variables['System.PullRequest.TargetBranch']))) | ||
displayName: '[Cache][Publish] Create cache directory' | ||
- bash: | | ||
# COMPUTE THE ESY INSTALL CACHE LOCATION AHEAD OF TIME | ||
# The cache location is only needed for some issues that require to remove | ||
# individual packages from cache (e.g. ocamlfind below) | ||
DESIRED_LEN="86" | ||
# Note: This will need to change when upgrading esy version | ||
# that reenables long paths on windows. | ||
if [ "$AGENT_OS" == "Windows_NT" ]; then | ||
DESIRED_LEN="33" | ||
fi | ||
HOME_ESY3="$HOME/.esy/3" | ||
HOME_ESY3_LEN=${#HOME_ESY3} | ||
NUM_UNDERS=$(echo "$(($DESIRED_LEN-$HOME_ESY3_LEN))") | ||
UNDERS=$(printf "%-${NUM_UNDERS}s" "_") | ||
UNDERS="${UNDERS// /_}" | ||
THE_ESY__CACHE_INSTALL_PATH=${HOME_ESY3}${UNDERS}/i | ||
if [ "$AGENT_OS" == "Windows_NT" ]; then | ||
THE_ESY__CACHE_INSTALL_PATH=$( cygpath --mixed --absolute "$THE_ESY__CACHE_INSTALL_PATH") | ||
fi | ||
echo "THE_ESY__CACHE_INSTALL_PATH: $THE_ESY__CACHE_INSTALL_PATH" | ||
# This will be exposed as an env var ESY__CACHE_INSTALL_PATH, or an | ||
# Azure var esy__cache_install_path | ||
echo "##vso[task.setvariable variable=esy__cache_install_path]$THE_ESY__CACHE_INSTALL_PATH" | ||
displayName: '[Cache] calculate esy store path' | ||
|
||
- task: Cache@2 | ||
inputs: | ||
# "v1" prefix added just to keep the ability to clear a cache without having to wait 7 days | ||
key: v1c | esy | $(Agent.OS) | esy.lock/index.json | ||
restoreKeys: v1c | esy | $(Agent.OS) | ||
path: _export | ||
cacheHitVar: CACHE_RESTORED | ||
displayName: '[Cache] esy packages' | ||
|
||
# TODO: This can be done in parallel with installing node, and esy | ||
# (which would save a bunch of time on windows) | ||
# Remove as soon as https://github.com/esy/esy/pull/969 is resolved. | ||
# For now, windows won't use build cache for problematic package. | ||
- task: Bash@3 | ||
condition: and(eq(variables['Build.Reason'], 'PullRequest'), and(succeeded(), ne(variables['Build.SourceBranch'], variables['System.PullRequest.TargetBranch']))) | ||
displayName: '[Cache][Restore] Restoring build cache using REST API' | ||
continueOnError: true | ||
condition: and(eq(variables['AGENT.OS'], 'Windows_NT'), eq(variables.CACHE_RESTORED, 'true')) | ||
displayName: 'Remove ocamlfind, rely and console prebuilts if on Windows' | ||
inputs: | ||
targetType: 'inline' # Optional. Options: filePath, inline | ||
script: | | ||
# If org name is reasonml then REST_BASE will be: https://dev.azure.com/reasonml/ | ||
REST_BASE="${SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}" | ||
PROJ="$SYSTEM_TEAMPROJECT" | ||
ART_NAME="cache-${AGENT_OS}-install" | ||
fetchLatestBuild() { | ||
PREFIX="branchName=refs%2Fheads%2F" | ||
BRANCH=${PREFIX}${SYSTEM_PULLREQUEST_TARGETBRANCH} | ||
FILTER='deletedFilter=excludeDeleted&statusFilter=completed&resultFilter=succeeded' | ||
LATEST='queryOrder=finishTimeDescending&$top=1' | ||
REST_BUILDS="$REST_BASE/$PROJ/_apis/build/builds?${FILTER}&${BRANCH}&${LATEST}&api-version=4.1" | ||
echo "Rest call for builds: $REST_BUILDS" | ||
REST_BUILDS_RESP=$(curl "$REST_BUILDS") | ||
if [[ $REST_BUILDS_RESP =~ (\"web\":\{\"href\":\")([^\"]*) ]]; then LATEST_BUILD_PAGE="${BASH_REMATCH[2]}"; else LATEST_BUILD_PAGE=""; fi | ||
if [[ $REST_BUILDS_RESP =~ (\"badge\":\{\"href\":\")([^\"]*) ]]; then LATEST_BUILD_BADGE="${BASH_REMATCH[2]}"; else LATEST_BUILD_BADGE=""; fi | ||
if [[ $REST_BUILDS_RESP =~ (\"id\":)([^,]*) ]]; then LATEST_BUILD_ID="${BASH_REMATCH[2]}"; else LATEST_BUILD_ID=""; fi | ||
} | ||
fetchLatestBuild | ||
fetchArtifactURL() { | ||
REST_ART="$REST_BASE/$PROJ/_apis/build/builds/$LATEST_BUILD_ID/artifacts?artifactName=$ART_NAME&api-version=4.1" | ||
echo "Rest call for artifacts: $REST_ART" | ||
if [[ $(curl $REST_ART) =~ (downloadUrl\":\")([^\"]*) ]]; then LATEST_ART_URL="${BASH_REMATCH[2]}"; else LATEST_ART_URL=""; fi | ||
} | ||
downloadArtifactAndContinue() { | ||
if [ -z "$LATEST_ART_URL" ] | ||
then | ||
echo "No latest artifact for merge-target branch found at URL $REST_ART" | ||
else | ||
curl "$LATEST_ART_URL" > "${BUILD_STAGINGDIRECTORY}/$ART_NAME.zip" | ||
PROJECT_DIR=$PWD | ||
cd $BUILD_STAGINGDIRECTORY | ||
unzip "$ART_NAME.zip" | ||
echo "Using Dependency cache for buildID: $LATEST_BUILD_ID" | ||
echo "Build log for build that produced the cache: $LATEST_BUILD_PAGE" | ||
echo "Build badge for build that produced the cache: $LATEST_BUILD_BADGE" | ||
echo "Build artifact from build that produced the cache: $LATEST_ART_URL" | ||
echo "Restoring build cache into:" | ||
mkdir -p $ESY__CACHE_INSTALL_PATH | ||
echo $ESY__CACHE_INSTALL_PATH | ||
echo "##vso[task.setvariable variable=esy_export_dir_to_import]${BUILD_STAGINGDIRECTORY}/${ART_NAME}/_export" | ||
if [[ -d ${ART_NAME}/_export ]]; then | ||
echo "Cached builds to import from ${ART_NAME}/_export in next CI step" | ||
ls ${ART_NAME}/_export | ||
mv ${ART_NAME}/_export ${PROJECT_DIR}/_export | ||
else | ||
echo "No _export directory to import from build cache" | ||
echo "Here's the contents of build cache:" | ||
find ${BUILD_STAGINGDIRECTORY} | ||
fi | ||
fi | ||
} | ||
fetchArtifactURL | ||
downloadArtifactAndContinue | ||
|
||
ls _export | ||
rm -r _export/opam__s__ocamlfind* | ||
rm -r _export/reason_native__s__rely* | ||
rm -r _export/reason_native__s__console* | ||
|
||
- powershell: esy.cmd import-dependencies | ||
continueOnError: true | ||
condition: and(eq(variables['AGENT.OS'], 'Windows_NT'), and(eq(variables['Build.Reason'], 'PullRequest'), and(succeeded(), ne(variables['Build.SourceBranch'], variables['System.PullRequest.TargetBranch'])))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This stuff was important (esy import-dependencies). Is it moved somewhere else? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happened was Azure changed the location of where our cache directory was on the physical file system, and so artifacts broke in future builds because the artifacts had hard coded paths in them. So I made sure that we actually ran (We can also use the REST API locally from laptops to pull down those caches and warm up our local development). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jordwalke Hm... I didn't realize this was added because of that. The path issue does not seem to be happening now (e.g. https://dev.azure.com/esy-ocaml/esy-ocaml/_build/results?buildId=421). Do you remember if this issue happened in specific situations or how could we repro it? Also, did it happen in all platforms? I was wondering if maybe the recent upgrade you did to Windows_2019 vm would have fixed that problem.
This is definitely a regression. I wonder if there is a way to expose the cache in the release artifacts? Reintroducing the REST API based flow would mean we would have to own again the issues with permissions, source and target branch handling etc which was one of the nice upsides of using Azure cache. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Some of the paths unexpectedly changed (the user directory where we have the esy cache for example). I don't believe they make any promises that it will not change unexpectedly. So I put the esy import/export in there because it guards against it ever changing in the future - as well as enabling the ability for us to use the cache to pull down artifacts from CI to warm up our laptops (it can't be done without first esy export-dependencies) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think I might not have been clear. What I was saying was that if the cache is in esy export-dependencies form, then it is trivial for local development machines (laptops) to have simple bash scripts that use the REST API and pull them down and magically speed up their local builds. (This is most important for Windows). Using I had to configure the |
||
condition: and(eq(variables['AGENT.OS'], 'Windows_NT'), eq(variables.CACHE_RESTORED, 'true')) | ||
displayName: "esy import-dependencies if windows (build cache from CI cache)" | ||
|
||
- bash: esy import-dependencies | ||
continueOnError: true | ||
condition: and(ne(variables['AGENT.OS'], 'Windows_NT'), and(eq(variables['Build.Reason'], 'PullRequest'), and(succeeded(), ne(variables['Build.SourceBranch'], variables['System.PullRequest.TargetBranch'])))) | ||
displayName: "esy import-dependencies if not windows (build cache from CI cache)" | ||
|
||
# Remove as soon as https://github.com/esy/esy/pull/969 is resolved. | ||
# For now, windows won't use build cache for problematic package. | ||
- task: Bash@3 | ||
continueOnError: true | ||
condition: and(eq(variables['AGENT.OS'], 'Windows_NT'), and(eq(variables['Build.Reason'], 'PullRequest'), and(succeeded(), ne(variables['Build.SourceBranch'], variables['System.PullRequest.TargetBranch'])))) | ||
displayName: 'Remove ocamlfind prebuilts if on Windows' | ||
inputs: | ||
targetType: 'inline' # Optional. Options: filePath, inline | ||
script: | | ||
ls ${ESY__CACHE_INSTALL_PATH} | ||
rm -r ${ESY__CACHE_INSTALL_PATH}/opam__s__ocamlfind* | ||
condition: and(ne(variables['AGENT.OS'], 'Windows_NT'), eq(variables.CACHE_RESTORED, 'true')) | ||
displayName: "esy import-dependencies if not windows (build cache from CI cache)" | ||
|
||
- bash: 'rm -rf _import' | ||
continueOnError: true | ||
condition: and(eq(variables['Build.Reason'], 'PullRequest'), and(succeeded(), ne(variables['Build.SourceBranch'], variables['System.PullRequest.TargetBranch']))) | ||
condition: eq(variables.CACHE_RESTORED, 'true') | ||
displayName: 'Remove import directory' | ||
|
||
- bash: 'rm -rf *' | ||
continueOnError: true | ||
workingDirectory: '$(Build.StagingDirectory)' | ||
condition: and(eq(variables['Build.Reason'], 'PullRequest'), and(succeeded(), ne(variables['Build.SourceBranch'], variables['System.PullRequest.TargetBranch']))) | ||
displayName: '[Cache][Restore] Clean up staging dir' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
# steps to install esy globally | ||
|
||
steps: | ||
- script: "npm install -g [email protected].6" | ||
- script: "npm install -g [email protected].8" | ||
displayName: "install esy" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also note that this here was required when running
export-dependencies
andimport-dependencies
because we can't have mingw tar shadowing the windows tar that we need.