Skip to content

Commit

Permalink
Replace octokit use with internal JSON file
Browse files Browse the repository at this point in the history
Python tags changes are slow so a static file makes sense. A new workflow is created to keep the file updated
  • Loading branch information
MatteoH2O1999 committed Jan 12, 2023
1 parent a179f31 commit 24180c4
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 71 deletions.
50 changes: 50 additions & 0 deletions .github/scripts/generate_tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const core = require('@actions/core');
const github = require('@actions/github');
const fs = require('fs');
const path = require('path');

async function updateJson() {
const octokit = github.getOctokit(process.env['GITHUB_TOKEN']);
const tags = [];
let index = 1;
let changed = true;
while (changed) {
changed = false;
let response = null;
core.startGroup(`Getting tags ${(index - 1) * 100}-${index * 100}`);
while (response === null) {
try {
response = await octokit.rest.repos.listTags({
owner: 'python',
page: index,
per_page: 100,
repo: 'cpython'
});
} catch (error) {
core.info('Rest API rate limit reached. Retrying in 60 seconds...');
await sleep(60);
}
}
if (response.status !== 200) {
throw new Error('Error in getting tags.');
}
for (const tag of response.data) {
changed = true;
core.info(`Received tag ${tag.name}`)
tags.push({version: tag.name, zipBall: tag.zipball_url});
}
core.endGroup();
index++;
}
return JSON.stringify(tags, null, 2);
}

const jsonPath = path.join(path.dirname(path.dirname(__dirname)), 'src', 'builder', 'tags.json');
core.info(`Updating ${jsonPath}`);

updateJson().then((jsonString) => {
core.startGroup('Final JSON string');
core.info(jsonString);
core.endGroup();
fs.writeFileSync(jsonPath, jsonString)
})
38 changes: 38 additions & 0 deletions .github/workflows/update_json.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Update JSON Data

on:
workflow_dispatch:
schedule:
- cron: 0 0 * * *

jobs:
update_cpython_tags:
runs-on: ubuntu-latest
name: Update CPython JSON tags
steps:
- name: Checkout code
uses: actions/checkout@v3
with:
ref: master
- name: Setup NodeJS 16
uses: actions/setup-node@v2
with:
node-version: 16
- name: Install dependencies
run: npm ci
- name: Update JSON data
run: node ./.github/scripts/generate_tags.js
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create or update pull request
uses: peter-evans/create-pull-request@v4
with:
commit-message: Update CPython JSON tags data
branch: create-pull-request/cpython-json-tags
delete-branch: true
title: Update CPython JSON tags data
body: |
Automated JSON data update by [update_json.yml](https://github.com/MatteoH2O1999/build-and-install-python/tree/master/.github/workflows/update_json.yml)
assignees: ${{ github.repository_owner }}
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
token: ${{ secrets.PAT_TOKEN }}
62 changes: 6 additions & 56 deletions src/builder/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,19 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

import * as core from '@actions/core';
import * as github from '@actions/github';
import * as semver from 'semver';
import {CPythonRepo, warnRateLimitThreshold} from '../constants';
import Builder from './builder';
import LinuxBuilder from './linux';
import MacOSBuilder from './darwin';
import {PythonVersion} from '../inputs';
import WindowsBuilder from './windows';
import cpythonTags from './tags.json';

export default async function getBuilder(
version: PythonVersion,
arch: string,
token: string
arch: string
): Promise<Builder | null> {
const specificVersion = await getSpecificVersion(version.version, token);
const specificVersion = await getSpecificVersion(version.version);
if (specificVersion === null) {
core.info(
`Could not resolve version range ${version.version} to any available CPython tag.`
Expand All @@ -51,54 +49,9 @@ export default async function getBuilder(
}

async function getSpecificVersion(
versionRange: string,
token: string
versionRange: string
): Promise<PythonTag | null> {
const tags: PythonTag[] = [];

// TODO: replace octokit with simple-git clone and tag-list

core.debug('Creating authenticated octokit');
const octokit = github.getOctokit(token);

const rateLimit = await octokit.rest.rateLimit.get();
if (rateLimit.data.resources.core.remaining < warnRateLimitThreshold) {
const currentTime = Date.now() / 1000;
const timeUntilReset =
(rateLimit.data.resources.core.reset - currentTime) / 60;
core.warning(
`Github API rate limit is almost reached. Only ${rateLimit.data.resources.core.remaining} requests are available for the next ${timeUntilReset} minutes.`
);
}

let index = 1;
let changed = true;
while (changed) {
changed = false;
let response = null;
core.debug(`Getting tags ${(index - 1) * 100}-${index * 100}...`);
while (response === null) {
try {
response = await octokit.rest.repos.listTags({
owner: CPythonRepo.OWNER,
page: index,
per_page: 100,
repo: CPythonRepo.REPO
});
} catch (error) {
core.info('Rest API rate limit reached. Retrying in 60 seconds...');
await sleep(60);
}
}
if (response.status !== 200) {
throw new Error('Error in getting tags.');
}
for (const tag of response.data) {
changed = true;
tags.push({version: tag.name, zipBall: tag.zipball_url});
}
index++;
}
const tags: PythonTag[] = cpythonTags;

let specificVersion: PythonTag | null = null;
for (const tag of tags) {
Expand All @@ -112,11 +65,8 @@ async function getSpecificVersion(
}
}
}
return specificVersion;
}

async function sleep(seconds: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
return specificVersion;
}

export type PythonTag = {
Expand Down
6 changes: 6 additions & 0 deletions src/builder/tags.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[
{
"version": "placeholder",
"zipBall": "url"
}
]
9 changes: 0 additions & 9 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,11 @@ export enum ManifestUrl {
BRANCH = 'main'
}

export enum CPythonRepo {
OWNER = 'python',
REPO = 'cpython'
}

const defaultPyPy2 = 'pypy2.7';
const defaultPyPy3 = 'pypy3.9';

export {defaultPyPy2, defaultPyPy3};

const warnRateLimitThreshold = 200;

export {warnRateLimitThreshold};

const windowsBuildDependencies = ['Microsoft.VisualStudio.Component.VC.140'];

const vsInstallerUrl = 'https://aka.ms/vs/17/release/vs_enterprise.exe';
Expand Down
6 changes: 1 addition & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,7 @@ export default async function main(): Promise<void> {
// Create builder

core.debug('Creating builder...');
const builder = await getBuilder(
inputs.version,
inputs.architecture,
inputs.token
);
const builder = await getBuilder(inputs.version, inputs.architecture);
core.debug('Builder created...');

// If builder is null, the version cannot be built from source
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"resolveJsonModule": true
},
"exclude": ["node_modules", "**/__tests__"]
}

0 comments on commit 24180c4

Please sign in to comment.