|  | 
|  | 1 | +'use strict' | 
|  | 2 | +const path = require('path'); | 
|  | 3 | +const fs = require('fs').promises; | 
|  | 4 | +const core = require('@actions/core'); | 
|  | 5 | +const {exec,getExecOutput} = require('@actions/exec'); | 
|  | 6 | +const yaml = require('js-yaml'); | 
|  | 7 | +const semver = require('semver'); | 
|  | 8 | +const https = require('https'); | 
|  | 9 | + | 
|  | 10 | +const SWIFT_ORG = 'swiftorg'; | 
|  | 11 | +const SWIFT_ORG_BUILD = path.join(SWIFT_ORG, '_data', 'builds'); | 
|  | 12 | +const SWIFT_ORG_CWD = {cwd: SWIFT_ORG}; | 
|  | 13 | + | 
|  | 14 | +async function swiftorgCommit() { | 
|  | 15 | +  const {stdout} = await getExecOutput('git', ['rev-parse', '--verify', 'HEAD'], SWIFT_ORG_CWD); | 
|  | 16 | +  return stdout.trim(); | 
|  | 17 | +} | 
|  | 18 | + | 
|  | 19 | +async function latestRelease() { | 
|  | 20 | +  const swiftRelease = path.join(SWIFT_ORG_BUILD, 'swift_releases.yml'); | 
|  | 21 | +  const releaseData = await fs.readFile(swiftRelease, 'utf-8'); | 
|  | 22 | +  const releases = yaml.load(releaseData); | 
|  | 23 | +  return releases[releases.length - 1]; | 
|  | 24 | +} | 
|  | 25 | + | 
|  | 26 | +async function latestDevRelease() { | 
|  | 27 | +  const buildEntries = await fs.readdir(SWIFT_ORG_BUILD, { withFileTypes: true }); | 
|  | 28 | +  const devBranchRegex = /swift-([^-]*)-branch/; | 
|  | 29 | +  const devDirs = buildEntries.flatMap(entry => { | 
|  | 30 | +      if (!entry.isDirectory() || !devBranchRegex.exec(entry.name)) { | 
|  | 31 | +          return []; | 
|  | 32 | +      } | 
|  | 33 | +      return entry.name; | 
|  | 34 | +  }).sort((dir1, dir2) => { | 
|  | 35 | +      const ver1 = devBranchRegex.exec(dir1)[1].replace('_', '.'); | 
|  | 36 | +      const ver2 = devBranchRegex.exec(dir2)[1].replace('_', '.'); | 
|  | 37 | +      return semver.gt(semver.coerce(ver2), semver.coerce(ver1)) ? 1 : -1; | 
|  | 38 | +  }); | 
|  | 39 | +  const devVer = devBranchRegex.exec(devDirs[0])[1].replace('_', '.'); | 
|  | 40 | +  const xcodeSnapshot = path.join(SWIFT_ORG_BUILD,devDirs[0], 'xcode.yml'); | 
|  | 41 | +  const devReleaseData = await fs.readFile(xcodeSnapshot, 'utf-8'); | 
|  | 42 | +  const devReleases = yaml.load(devReleaseData); | 
|  | 43 | +  return { name: devVer, date: devReleases[0].date, tag: devReleases[0].dir }; | 
|  | 44 | +} | 
|  | 45 | + | 
|  | 46 | +async function latestSnapshot() { | 
|  | 47 | +  const xcodeSnapshot = path.join(SWIFT_ORG_BUILD, 'development', 'xcode.yml'); | 
|  | 48 | +  const devSnapshotsData = await fs.readFile(xcodeSnapshot, 'utf-8'); | 
|  | 49 | +  const snapshots = yaml.load(devSnapshotsData); | 
|  | 50 | +  return { date: snapshots[0].date, tag: snapshots[0].dir }; | 
|  | 51 | +} | 
|  | 52 | + | 
|  | 53 | +exports.update = async () => { | 
|  | 54 | +  const commit = await swiftorgCommit(); | 
|  | 55 | +  const release = await latestRelease(); | 
|  | 56 | +  const dev = await latestDevRelease(); | 
|  | 57 | +  const snapshot = await latestSnapshot(); | 
|  | 58 | + | 
|  | 59 | +  const swiftorg = { commit: commit, release: release, dev: dev, snapshot: snapshot }; | 
|  | 60 | +  const data = JSON.stringify(swiftorg); | 
|  | 61 | +  core.info(`Updating swiftorg metadata to "${data}"`); | 
|  | 62 | +  const metadata = path.join('pages', 'metadata.json'); | 
|  | 63 | +  await fs.mkdir(path.dirname(metadata), {recursive: true}); | 
|  | 64 | +  await fs.writeFile(metadata, data, 'utf-8'); | 
|  | 65 | +  return data; | 
|  | 66 | +}; | 
|  | 67 | + | 
|  | 68 | +exports.currentData = async () => { | 
|  | 69 | +  return new Promise((resolve, reject) => { | 
|  | 70 | +    https.get( | 
|  | 71 | +      'https://swiftylab.github.io/setup-swift/metadata.json', | 
|  | 72 | +      res => { | 
|  | 73 | +        const {statusCode} = res | 
|  | 74 | +        const contentType = res.headers['content-type'] | 
|  | 75 | + | 
|  | 76 | +        let error | 
|  | 77 | +        if (statusCode !== 200) { | 
|  | 78 | +          error = new Error(`Request Failed Status Code: '${statusCode}'`) | 
|  | 79 | +        } else if (!contentType?.startsWith('application/json')) { | 
|  | 80 | +          error = new Error(`Invalid content-type: ${contentType}`) | 
|  | 81 | +        } | 
|  | 82 | + | 
|  | 83 | +        if (error) { | 
|  | 84 | +          core.error(error.message) | 
|  | 85 | +          res.resume() | 
|  | 86 | +          reject(error) | 
|  | 87 | +          return | 
|  | 88 | +        } | 
|  | 89 | + | 
|  | 90 | +        let rawData = '' | 
|  | 91 | +        res.setEncoding('utf8') | 
|  | 92 | +        res.on('data', chunk => { | 
|  | 93 | +          rawData += chunk | 
|  | 94 | +        }) | 
|  | 95 | +        res.on('end', () => { | 
|  | 96 | +          try { | 
|  | 97 | +            const parsedData = JSON.parse(rawData) | 
|  | 98 | +            core.debug(`Recieved swift.org metadata: "${rawData}"`) | 
|  | 99 | +            resolve(parsedData) | 
|  | 100 | +          } catch (e) { | 
|  | 101 | +            core.error(`Parsing swift.org metadata error: '${e}'`) | 
|  | 102 | +            reject(e) | 
|  | 103 | +          } | 
|  | 104 | +        }) | 
|  | 105 | +      } | 
|  | 106 | +    ) | 
|  | 107 | +  }) | 
|  | 108 | +} | 
|  | 109 | + | 
|  | 110 | +exports.fetch = async () => { | 
|  | 111 | +  let checkoutData; | 
|  | 112 | +  if (process.env.SETUPSWIFT_SWIFTORG_METADATA) { | 
|  | 113 | +    checkoutData = JSON.parse(process.env.SETUPSWIFT_SWIFTORG_METADATA); | 
|  | 114 | +  }  | 
|  | 115 | +  if (!checkoutData || !checkoutData.commit) { | 
|  | 116 | +    checkoutData = await this.currentData(); | 
|  | 117 | +  } | 
|  | 118 | +  const origin = 'https://github.com/apple/swift-org-website.git' | 
|  | 119 | +  const ref = checkoutData.commit | 
|  | 120 | +  await exec('git', ['init', SWIFT_ORG]) | 
|  | 121 | +  await exec('git', ['fetch', origin, ref, '--depth=1', '--no-tags'], SWIFT_ORG_CWD) | 
|  | 122 | +  await exec('git', ['checkout', 'FETCH_HEAD', '--detach'], SWIFT_ORG_CWD) | 
|  | 123 | +} | 
0 commit comments