add expo-updates github action (#3270)
* add expo-updates github action * add two scripts
This commit is contained in:
		
							parent
							
								
									a02d5f9eb9
								
							
						
					
					
						commit
						9277282e6c
					
				
					 5 changed files with 206 additions and 1 deletions
				
			
		
							
								
								
									
										55
									
								
								.github/workflows/bundle-deploy-eas-update.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								.github/workflows/bundle-deploy-eas-update.yml
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
---
 | 
			
		||||
name: Bundle and Deploy EAS Update
 | 
			
		||||
 | 
			
		||||
on:
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
    inputs:
 | 
			
		||||
      runtimeVersion:
 | 
			
		||||
        type: string
 | 
			
		||||
        description: Runtime version (in x.x.x format) that this update is for
 | 
			
		||||
        required: true
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  bundleDeploy:
 | 
			
		||||
    name: Bundle and Deploy EAS Update
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: 🧐 Validate version
 | 
			
		||||
        run: |
 | 
			
		||||
          [[ "${{ github.event.inputs.runtimeVersion }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && echo "Version is valid" || exit 1
 | 
			
		||||
 | 
			
		||||
      - name: ⬇️ Checkout
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
 | 
			
		||||
      - name: 🔧 Setup Node
 | 
			
		||||
        uses: actions/setup-node@v4
 | 
			
		||||
        with:
 | 
			
		||||
          node-version-file: .nvmrc
 | 
			
		||||
          cache: yarn
 | 
			
		||||
 | 
			
		||||
      - name: ⚙️ Install Dependencies
 | 
			
		||||
        run: yarn install
 | 
			
		||||
 | 
			
		||||
      - name: 🪛 Install jq
 | 
			
		||||
        uses: dcarbone/install-jq-action@v2
 | 
			
		||||
 | 
			
		||||
      - name: ⛏️ Setup Expo
 | 
			
		||||
        run: yarn global add eas-cli-local-build-plugin
 | 
			
		||||
 | 
			
		||||
      - name: 🔤 Compile Translations
 | 
			
		||||
        run: yarn intl:build
 | 
			
		||||
 | 
			
		||||
      - name: ✏️ Write environment variables
 | 
			
		||||
        run: |
 | 
			
		||||
          export json='${{ secrets.GOOGLE_SERVICES_TOKEN }}'
 | 
			
		||||
          echo "${{ secrets.ENV_TOKEN }}" > .env
 | 
			
		||||
          echo "$json" > google-services.json
 | 
			
		||||
 | 
			
		||||
      - name: 🏗️ Create Bundle
 | 
			
		||||
        run: yarn export
 | 
			
		||||
 | 
			
		||||
      - name: 📦 Package Bundle and 🚀 Deploy
 | 
			
		||||
        run: yarn make-deploy-bundle
 | 
			
		||||
        env:
 | 
			
		||||
          DENIS_API_KEY: ${{ secrets.DENIS_API_KEY }}
 | 
			
		||||
          RUNTIME_VERSION: ${{ github.event.inputs.runtimeVersion }}
 | 
			
		||||
							
								
								
									
										18
									
								
								code-signing/certificate.pem
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								code-signing/certificate.pem
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIC0TCCAbmgAwIBAgIJcMN2yt5KNDqTMA0GCSqGSIb3DQEBCwUAMBIxEDAOBgNV
 | 
			
		||||
BAMTB0JsdWVza3kwHhcNMjQwMzE0MDA1OTU4WhcNMzQwMzE0MDA1OTU4WjASMRAw
 | 
			
		||||
DgYDVQQDEwdCbHVlc2t5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
 | 
			
		||||
izSAWEc3wRoa3eTBEh/kE9pH0d6jhEGw9GrYfei60MHT1pSq2cTdyUM1yUZchAeW
 | 
			
		||||
gFFtqFxX0pfIZQyMlIZbjkaOxOqzWhB0aCsxngnhbSahFwRxkVwTAuonhqIpaLBL
 | 
			
		||||
hrCCCQ2IfZUpy8QeasqlTlmvmijuCC34fXxJlxNcj8SqzIZi+civ7U5PMPfIMMnD
 | 
			
		||||
tCDIBy1vxMk57m25X2ikcWUFW64qNVLkFAL36xEnmFTL4Ivqpz23gUcUIe1zbesY
 | 
			
		||||
jAgDtlwnAE7mU3oagCUDcSuOveT4POhT35Xp3Y/07I68kmXtrPxwd5k0L0zbisEm
 | 
			
		||||
poKZ87E2X29BitihicMpBwIDAQABoyowKDAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0l
 | 
			
		||||
AQH/BAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAED1gdMF0yr8Gy87
 | 
			
		||||
RgyaeVpPySwSsO0selmXXrcmOWgiPA05lubyhFEa4P5kdzBEByG2MT+pJkjGYpvK
 | 
			
		||||
XRnqXM5VvdS2RhYYFH0cFOIUqBKwCnzViCMuGQeoGUx4oPcKFS0PQ1WjW2d4pS75
 | 
			
		||||
51GBfB6LOepsCHUG0A9XEk7EAyUWc4M2ITCJsTtJh8CVn2pTks2q14ETDs86YQv4
 | 
			
		||||
peDaJv8nhIe8oQkeGn2o/P/ctkwJg/uBydQUsWgjjGTQZTilVjGTW1mwDr9FucAE
 | 
			
		||||
d5gKIk4rtR/3Zd/NDdqp8PrkoWeVM7Hwr789/mpUOeqa/j7YNkDYQh7x+M/odd1D
 | 
			
		||||
KY0bQEQ=
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +41,9 @@
 | 
			
		|||
    "intl:extract": "lingui extract",
 | 
			
		||||
    "intl:compile": "lingui compile",
 | 
			
		||||
    "nuke": "rm -rf ./node_modules && rm -rf ./ios && rm -rf ./android",
 | 
			
		||||
    "update-extensions": "scripts/updateExtensions.sh"
 | 
			
		||||
    "update-extensions": "bash scripts/updateExtensions.sh",
 | 
			
		||||
    "export": "npx expo export",
 | 
			
		||||
    "make-deploy-bundle": "bash scripts/bundleUpdate.sh"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@atproto/api": "^0.12.0",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										104
									
								
								scripts/bundleUpdate.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								scripts/bundleUpdate.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,104 @@
 | 
			
		|||
const crypto = require('crypto')
 | 
			
		||||
const fs = require('fs')
 | 
			
		||||
const fsp = fs.promises
 | 
			
		||||
const path = require('path')
 | 
			
		||||
 | 
			
		||||
const DIST_DIR = './dist'
 | 
			
		||||
const BUNDLES_DIR = '/_expo/static/js'
 | 
			
		||||
const IOS_BUNDLE_DIR = path.join(DIST_DIR, BUNDLES_DIR, '/ios')
 | 
			
		||||
const ANDROID_BUNDLE_DIR = path.join(DIST_DIR, BUNDLES_DIR, '/android')
 | 
			
		||||
const METADATA_PATH = path.join(DIST_DIR, '/metadata.json')
 | 
			
		||||
const DEST_DIR = './bundleTempDir'
 | 
			
		||||
 | 
			
		||||
// Weird, don't feel like figuring out _why_ it wants this
 | 
			
		||||
const METADATA = require(`../${METADATA_PATH}`)
 | 
			
		||||
const IOS_METADATA_ASSETS = METADATA.fileMetadata.ios.assets
 | 
			
		||||
const ANDROID_METADATA_ASSETS = METADATA.fileMetadata.android.assets
 | 
			
		||||
 | 
			
		||||
const getMd5 = async path => {
 | 
			
		||||
  return new Promise(res => {
 | 
			
		||||
    const hash = crypto.createHash('md5')
 | 
			
		||||
    const rStream = fs.createReadStream(path)
 | 
			
		||||
    rStream.on('data', data => {
 | 
			
		||||
      hash.update(data)
 | 
			
		||||
    })
 | 
			
		||||
    rStream.on('end', () => {
 | 
			
		||||
      res(hash.digest('hex'))
 | 
			
		||||
    })
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const moveFiles = async () => {
 | 
			
		||||
  console.log('Making directory...')
 | 
			
		||||
  await fsp.mkdir(DEST_DIR)
 | 
			
		||||
  await fsp.mkdir(path.join(DEST_DIR, '/assets'))
 | 
			
		||||
 | 
			
		||||
  console.log('Getting ios md5...')
 | 
			
		||||
  const iosCurrPath = path.join(
 | 
			
		||||
    IOS_BUNDLE_DIR,
 | 
			
		||||
    (await fsp.readdir(IOS_BUNDLE_DIR))[0],
 | 
			
		||||
  )
 | 
			
		||||
  const iosMd5 = await getMd5(iosCurrPath)
 | 
			
		||||
  const iosNewPath = `bundles/${iosMd5}.bundle`
 | 
			
		||||
 | 
			
		||||
  console.log('Copying ios bundle...')
 | 
			
		||||
  await fsp.cp(iosCurrPath, path.join(DEST_DIR, iosNewPath))
 | 
			
		||||
 | 
			
		||||
  console.log('Getting android md5...')
 | 
			
		||||
  const androidCurrPath = path.join(
 | 
			
		||||
    ANDROID_BUNDLE_DIR,
 | 
			
		||||
    (await fsp.readdir(ANDROID_BUNDLE_DIR))[0],
 | 
			
		||||
  )
 | 
			
		||||
  const androidMd5 = await getMd5(androidCurrPath)
 | 
			
		||||
  const androidNewPath = `bundles/${androidMd5}.bundle`
 | 
			
		||||
 | 
			
		||||
  console.log('Copying android bundle...')
 | 
			
		||||
  await fsp.cp(androidCurrPath, path.join(DEST_DIR, androidNewPath))
 | 
			
		||||
 | 
			
		||||
  const iosAssets = []
 | 
			
		||||
  const androidAssets = []
 | 
			
		||||
 | 
			
		||||
  console.log('Getting ios asset md5s and moving them...')
 | 
			
		||||
  for (const asset of IOS_METADATA_ASSETS) {
 | 
			
		||||
    const currPath = path.join(DIST_DIR, asset.path)
 | 
			
		||||
    const md5 = await getMd5(currPath)
 | 
			
		||||
    const withExtPath = `assets/${md5}.${asset.ext}`
 | 
			
		||||
    iosAssets.push(withExtPath)
 | 
			
		||||
    await fsp.cp(currPath, path.join(DEST_DIR, withExtPath))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  console.log('Getting android asset md5s and moving them...')
 | 
			
		||||
  for (const asset of ANDROID_METADATA_ASSETS) {
 | 
			
		||||
    const currPath = path.join(DIST_DIR, asset.path)
 | 
			
		||||
    const md5 = await getMd5(currPath)
 | 
			
		||||
    const withExtPath = `assets/${md5}.${asset.ext}`
 | 
			
		||||
    androidAssets.push(withExtPath)
 | 
			
		||||
    await fsp.cp(currPath, path.join(DEST_DIR, withExtPath))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const result = {
 | 
			
		||||
    version: 0,
 | 
			
		||||
    bundler: 'metro',
 | 
			
		||||
    fileMetadata: {
 | 
			
		||||
      ios: {
 | 
			
		||||
        bundle: iosNewPath,
 | 
			
		||||
        assets: iosAssets,
 | 
			
		||||
      },
 | 
			
		||||
      android: {
 | 
			
		||||
        bundle: androidNewPath,
 | 
			
		||||
        assets: androidAssets,
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  console.log('Writing metadata...')
 | 
			
		||||
  await fsp.writeFile(
 | 
			
		||||
    path.join(DEST_DIR, 'metadata.json'),
 | 
			
		||||
    JSON.stringify(result),
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  console.log('Finished!')
 | 
			
		||||
  console.log('Metadata:', result)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
moveFiles()
 | 
			
		||||
							
								
								
									
										26
									
								
								scripts/bundleUpdate.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								scripts/bundleUpdate.sh
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
#!/bin/bash
 | 
			
		||||
set -o errexit
 | 
			
		||||
set -o pipefail
 | 
			
		||||
set -o nounset
 | 
			
		||||
 | 
			
		||||
rm -rf bundleTempDir
 | 
			
		||||
rm -rf bundle.tar.gz
 | 
			
		||||
 | 
			
		||||
echo "Creating tarball..."
 | 
			
		||||
node scripts/bundleUpdate.js
 | 
			
		||||
 | 
			
		||||
cd bundleTempDir || exit
 | 
			
		||||
 | 
			
		||||
BUNDLE_VERSION=$(date +%s)
 | 
			
		||||
DEPLOYMENT_URL="https://updates.bsky.app/v1/upload?runtime-version=$RUNTIME_VERSION&bundle-version=$BUNDLE_VERSION"
 | 
			
		||||
 | 
			
		||||
tar czvf bundle.tar.gz ./*
 | 
			
		||||
 | 
			
		||||
echo "Deploying to $DEPLOYMENT_URL..."
 | 
			
		||||
 | 
			
		||||
curl -o - --form "bundle=@./bundle.tar.gz" --user "bsky:$DENIS_API_KEY" --basic "$DEPLOYMENT_URL"
 | 
			
		||||
 | 
			
		||||
cd ..
 | 
			
		||||
 | 
			
		||||
rm -rf bundleTempDir
 | 
			
		||||
rm -rf bundle.tar.gz
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue