name: ci-artifacts on: push: branches: - main pull_request: # For the continuous `ci-artifacts` release permissions: contents: write env: LC_CTYPE: C.UTF-8 jobs: minimal-sdk-artifact: if: github.repository_owner == 'git-for-windows' runs-on: [Windows, ARM64] steps: - name: clone git-sdk-arm64 run: | git init --bare git-sdk-arm64.git && git --git-dir=git-sdk-arm64.git remote add origin /~https://github.com/${{github.repository}} && git --git-dir=git-sdk-arm64.git config remote.origin.promisor true && git --git-dir=git-sdk-arm64.git config remote.origin.partialCloneFilter blob:none && git --git-dir=git-sdk-arm64.git fetch --depth=1 origin ${{github.sha}} && git --git-dir=git-sdk-arm64.git update-ref --no-deref HEAD ${{github.sha}} - name: clone build-extra run: git clone --depth=1 --single-branch -b main /~https://github.com/git-for-windows/build-extra - name: build git-sdk-arm64-minimal-sdk shell: bash run: | sh -x ./build-extra/please.sh create-sdk-artifact --sdk=git-sdk-arm64.git minimal-sdk && cygpath -aw minimal-sdk/usr/bin >>$GITHUB_PATH - name: compress artifact shell: bash run: mkdir artifacts && (cd minimal-sdk && tar cvf - * .[0-9A-Za-z]*) | gzip -1 >artifacts/git-sdk-aarch64-minimal.tar.gz - name: create zip and 7z SFX variants of the minimal SDK if: github.event_name == 'push' && github.ref == 'refs/heads/main' shell: bash run: | for path in clangarm64/bin/7z.exe clangarm64/bin/7z.dll clangarm64/lib/7zip/7zCon.sfx clangarm64/bin/libc++.dll do git --git-dir=git-sdk-arm64.git show HEAD:$path >${path##*/} done && (cd minimal-sdk && ../7z.exe a -mmt=on -mx9 ../artifacts/git-sdk-aarch64-minimal.zip * .?*) && (cd minimal-sdk && ../7z.exe a -t7z -mmt=on -m0=lzma -mqs -mlc=8 -mx=9 -md=256M -mfb=273 -ms=256M -sfx../7zCon.sfx \ ../artifacts/git-sdk-aarch64-minimal.7z.exe * .?*) - name: run some tests shell: bash run: | set -x . /etc/profile # cygpath works test "$(cygpath -aw /)" = "${{github.workspace}}\minimal-sdk" || exit 1 # comes with Clang and can compile a DLL test "$(type -p clang)" = "/clangarm64/bin/clang" || exit 1 cat >dll.c <<-\EOF && __attribute__((dllexport)) int increment(int i) { return i + 1; } EOF clang -Wall -g -O2 -shared -o sample.dll dll.c || exit 1 ls -la # stat works test "stat is /usr/bin/stat" = "$(type stat)" || exit 1 stat /usr/bin/stat.exe || exit 1 # unzip works test "unzip is /usr/bin/unzip" = "$(type unzip)" || exit 1 git init unzip-test && echo TEST >unzip-test/README && git -C unzip-test add -A && git -C unzip-test -c user.name=A -c user.email=b@c.d commit -m 'Testing, testing...' && git --git-dir=unzip-test/.git archive -o test.zip HEAD && unzip -v test.zip >unzip-test.out && cat unzip-test.out && test "grep is /usr/bin/grep" = "$(type grep)" || exit 1 grep README unzip-test.out - name: publish release assets if: github.event_name == 'push' && github.ref == 'refs/heads/main' uses: actions/github-script@v7 with: script: | process.chdir('artifacts') const req = { owner: context.repo.owner, repo: context.repo.repo } // find or create the GitHub release named `ci-artifacts` const release = await (async () => { try { return await github.rest.repos.getReleaseByTag({ ...req, tag: 'ci-artifacts' }); } catch (e) { if (e.status === 404) { // create the `ci-artifacts` GitHub release based on the current revision const workflowRunsURL = `${context.serverUrl}/${ process.env.GITHUB_WORKFLOW_REF.replace(/\/\.github\/workflows\/([^@]+).*/, '/actions/workflows/$1') }` return await github.rest.repos.createRelease({ ... req, tag_name: 'ci-artifacts', body: `Continuous release of \`ci-artifacts\` This release is automatically updated by the [ci-artifacts](${workflowRunsURL}) workflow. For technical reasons, allow up to a minute for release assets to be missing while they are updated.`, }); } throw e; } })() const fs = require('fs') for (const fileName of [ 'git-sdk-aarch64-minimal.tar.gz', 'git-sdk-aarch64-minimal.zip', 'git-sdk-aarch64-minimal.7z.exe', ]) { console.log(`Uploading ${fileName}`) const uploadReq = { ...req, release_id: release.data.id, name: fileName, headers: { 'content-length': (await fs.promises.stat(fileName)).size, }, data: fs.createReadStream(fileName), } // if the asset does not yet exist, simply upload it const originalAsset = release.data.assets.filter(asset => asset.name === fileName).pop() if (!originalAsset) { const asset = await github.rest.repos.uploadReleaseAsset(uploadReq) console.log(`Uploaded to ${asset.data.browser_download_url}`) continue } // otherwise upload it using a temporary file name, // then delete the old asset // and then rename the new asset; // this way, the asset is not missing for a long time const asset = await github.rest.repos.uploadReleaseAsset({ ...uploadReq, name: `tmp.${fileName}` }) await github.rest.repos.deleteReleaseAsset({ ...req, asset_id: originalAsset.id }) const updatedAsset = await github.rest.repos.updateReleaseAsset({...req, asset_id: asset.data.id, name: fileName, label: fileName, }) console.log(`Updated ${updatedAsset.data.browser_download_url}`) } await github.rest.git.updateRef({ ...req, ref: 'tags/ci-artifacts', sha: process.env.GITHUB_SHA, })