Skip to content

Commit c439ac4

Browse files
committed
Merge branch 'master' of https://github.com/juce-framework/JUCE
2 parents 089f295 + 501c076 commit c439ac4

3,517 files changed

Lines changed: 650070 additions & 199732 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,11 @@ body:
4848
multiple: true
4949
options:
5050
- x86_64
51-
- ARM
52-
- Other
53-
- 64-bit
54-
- 32-bit
51+
- Arm64/aarch64
52+
- Arm64EC (Windows)
53+
- x86 (Windows, Android)
54+
- 32 bit Arm (Linux, Android)
55+
- Unsupported
5556
validations:
5657
required: true
5758
- type: textarea
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Download Artifacts
2+
description: Download artifacts preserving file permissions
3+
inputs:
4+
keys:
5+
description: The artifact keys
6+
required: true
7+
runs:
8+
using: composite
9+
steps:
10+
- name: Download artifacts
11+
shell: python3 {0}
12+
run: |
13+
import sys
14+
import os
15+
sys.path.append(os.path.abspath('.github/workflows'))
16+
17+
from configure_logger import configure_logger
18+
from github_api_request import json_github_api_request, download_github_api_request
19+
20+
from logging import getLogger
21+
from os import environ
22+
from zipfile import ZipFile
23+
import tarfile
24+
25+
logger = getLogger(__name__)
26+
configure_logger(logger)
27+
28+
input_keys = """${{ inputs.keys }}"""
29+
logger.debug(f'Input keys: {input_keys}')
30+
artifact_keys = list(filter(None, [x.strip() for x in input_keys.split('\n')]))
31+
logger.info(f'Downloading keys: {artifact_keys}')
32+
33+
api_prefix = 'actions'
34+
artifacts_info = json_github_api_request(f'{api_prefix}/runs/{environ["GITHUB_RUN_ID"]}/artifacts')
35+
36+
for key in artifact_keys:
37+
artifact_id = [x['id'] for x in artifacts_info['artifacts'] if x['name'] == key][0]
38+
logger.debug(f'Artifact id for {key}: {artifact_id}')
39+
zip_file = f'{key}.zip'
40+
download_github_api_request(zip_file, f'{api_prefix}/artifacts/{artifact_id}/zip')
41+
logger.debug(f'Unzipping: {zip_file}')
42+
with ZipFile(zip_file) as archive:
43+
archive.extractall()
44+
os.remove(zip_file)
45+
tar_file = f'{key}.tar'
46+
logger.debug(f'Extracting: {tar_file}')
47+
with tarfile.open(tar_file, 'r') as tar:
48+
tar.extractall()
49+
os.remove(tar_file)
50+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Job Wrapper
2+
description: Setup and cleanup for build jobs
3+
inputs:
4+
artifacts:
5+
description: Required artifacts
6+
required: false
7+
default: ''
8+
command:
9+
description: The build command
10+
required: true
11+
runs:
12+
using: composite
13+
steps:
14+
- name: Get artifacts
15+
uses: ./.github/actions/download_artifacts
16+
with:
17+
keys: |
18+
JUCE-utils
19+
${{ inputs.artifacts }}
20+
- run: ${{ inputs.command }}
21+
shell: ${{ runner.os == 'Windows' && 'powershell' || 'bash' }}
22+
- name: Handle job failure
23+
if: failure()
24+
run: python3 JUCE-utils/.github/workflows/post_job.py
25+
shell: ${{ runner.os == 'Windows' && 'powershell' || 'bash' }}
26+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Upload Artifact
2+
description: Upload an artifact preserving file permissions
3+
inputs:
4+
key:
5+
description: The artifact key
6+
required: true
7+
paths:
8+
description: The artifact paths
9+
required: true
10+
runs:
11+
using: composite
12+
steps:
13+
- name: Create tarball
14+
shell: python3 {0}
15+
run: |
16+
import sys
17+
import os
18+
sys.path.append(os.path.abspath('.github/workflows'))
19+
20+
from configure_logger import configure_logger
21+
22+
from logging import getLogger
23+
from os import mkdir
24+
import tarfile
25+
26+
logger = getLogger(__name__)
27+
configure_logger(logger)
28+
29+
input_paths = """${{ inputs.paths }}"""
30+
logger.debug(f'Input paths: {input_paths}')
31+
paths = filter(None, [x.strip() for x in input_paths.split('\n')])
32+
logger.info(f'Uploading paths: {paths}')
33+
mkdir('tmp_artifact_upload')
34+
archive_path = 'tmp_artifact_upload/${{ inputs.key }}.tar'
35+
logger.debug(f'Creating archive: {archive_path}')
36+
with tarfile.open('tmp_artifact_upload/${{ inputs.key }}.tar', 'w') as tar:
37+
for path in paths:
38+
logger.debug(f'Adding path to archive archive: {path}')
39+
tar.add(path)
40+
- uses: actions/upload-artifact@v4.6.0
41+
with:
42+
name: ${{ inputs.key }}
43+
path: tmp_artifact_upload
44+
retention-days: 1
45+
- name: Clean up
46+
shell: python3 {0}
47+
run: |
48+
from shutil import rmtree
49+
rmtree('tmp_artifact_upload')
50+

.github/workflows/check-cla.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ jobs:
77
PR_NUMBER: ${{ github.event.number }}
88
steps:
99
- name: check-CLA
10+
if: github.repository == 'juce-framework/JUCE'
1011
run: |
1112
import urllib.request
1213
import json
@@ -18,6 +19,7 @@ jobs:
1819
with urllib.request.urlopen(req) as response:
1920
return json.loads(response.read().decode('utf-8'))
2021
prCommits = jsonRequest('https://api.github.com/repos/juce-framework/JUCE/pulls/${{ github.event.number }}/commits')
22+
print(f'Commit info:\n{json.dumps(prCommits, indent=4)}')
2123
allAuthors = [commit[authorType]['login'] for authorType in ['author', 'committer'] for commit in prCommits if commit[authorType]]
2224
uniqueAuthors = [name for name in list(set(allAuthors)) if name != 'web-flow']
2325
if (len(uniqueAuthors) == 0):
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import logging
2+
from os import getenv
3+
from sys import stdout
4+
5+
def configure_logger(logger):
6+
handler = logging.StreamHandler(stdout)
7+
formatter = logging.Formatter('[%(name)s] %(message)s')
8+
handler.setFormatter(formatter)
9+
level = logging.DEBUG if (getenv('RUNNER_DEBUG', '0').lower() not in ('0', 'f', 'false')) else logging.INFO
10+
logger.setLevel(level)
11+
handler.setLevel(level)
12+
logger.addHandler(handler)
13+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from configure_logger import configure_logger
2+
3+
from logging import getLogger
4+
from urllib.request import Request, urlopen
5+
from urllib.error import HTTPError, URLError
6+
from json import dumps, loads
7+
from os import environ
8+
from shutil import copyfileobj
9+
from time import sleep
10+
11+
logger = getLogger(__name__)
12+
configure_logger(logger)
13+
14+
def github_api_request(path, method='GET', data=None):
15+
url = f'https://api.github.com/repos/{environ["GITHUB_REPOSITORY"]}/{path}'
16+
logger.debug(f'Requesting GitHub API: {url}')
17+
serialised_data = dumps(data).encode('utf-8') if data else None
18+
if serialised_data:
19+
logger.debug(f'Data: {serialised_data}')
20+
req = Request(
21+
url=url,
22+
method=method,
23+
headers={
24+
'Accept': 'application/vnd.github+json',
25+
'X-GitHub-Api-Version': '2022-11-28'
26+
},
27+
data=serialised_data
28+
)
29+
req.add_unredirected_header('Authorization', f'Bearer {environ["GITHUB_API_TOKEN"]}')
30+
num_attempts = 0
31+
while True:
32+
response = None
33+
try:
34+
response = urlopen(req)
35+
return response
36+
except (HTTPError, URLError) as e:
37+
num_attempts += 1
38+
if num_attempts == 3:
39+
logger.warning(f'GitHub API access failed\n{e.reason}\n{e.headers}\n{e.fp.read()}')
40+
raise e
41+
logger.debug(f'Request attempt {num_attempts} failed, retrying')
42+
sleep(10)
43+
44+
def json_github_api_request(path, method='GET', data=None):
45+
with github_api_request(path, method, data) as response:
46+
result = loads(response.read().decode('utf-8'))
47+
logger.debug(f'GitHub API result: {result}')
48+
return result
49+
50+
def download_github_api_request(filename, path, method='GET', data=None):
51+
with github_api_request(path, method, data) as response:
52+
with open(filename, 'wb') as f:
53+
copyfileobj(response, f)
54+
logger.debug(f'Downloaded to: {filename}')
55+
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: JUCE Private Build
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
triggerer:
7+
required: false
8+
type: string
9+
default: ''
10+
description: The GitHub ID to receive email notifications (leave blank)
11+
nightly-targets:
12+
required: false
13+
type: string
14+
default: "[]"
15+
description: A list of nightly build targets in JSON format
16+
cpp-std:
17+
required: false
18+
type: string
19+
default: ""
20+
description: The C++ standard to use (optional [20, 23])
21+
22+
env:
23+
target_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
24+
25+
run-name: "[${{ inputs.triggerer && inputs.triggerer || github.event.sender.login }}] ${{ github.sha }}"
26+
27+
jobs:
28+
setup:
29+
if: ${{ (inputs.nightly-targets == '[]') && (inputs.cpp-std == '') }}
30+
name: Check and set CI commit status
31+
runs-on: ubuntu-latest
32+
env:
33+
GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
34+
outputs:
35+
build: ${{ steps.status_check.outputs.build }}
36+
steps:
37+
- uses: actions/checkout@v4.2.2
38+
with:
39+
fetch-depth: 0
40+
sparse-checkout: |
41+
.github/workflows
42+
- id: status_check
43+
shell: python
44+
run: |
45+
import sys
46+
import os
47+
sys.path.append(os.path.abspath('.github/workflows'))
48+
from github_api_request import json_github_api_request
49+
sha = os.environ["GITHUB_SHA"]
50+
statuses_response = json_github_api_request(f'commits/{sha}/statuses')
51+
status = next(filter(lambda x: x['context'] == 'CI', statuses_response), None)
52+
if (status is None) or (status['state'] != 'success'):
53+
with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
54+
f.write(f'build=1\n')
55+
data = {
56+
'state': 'pending',
57+
'context': 'CI',
58+
'target_url': os.environ['target_url'],
59+
}
60+
post_response = json_github_api_request(f'statuses/{sha}', 'POST', data)
61+
print(post_response)
62+
build:
63+
if: ${{ !cancelled() && (success() || needs.setup.result == 'skipped') && (inputs.nightly-targets != '[]' || inputs.cpp-std != '' || needs.setup.outputs.build == '1' || contains(fromJSON('["master"]'), github.ref_name)) }}
64+
needs: [setup]
65+
name: .
66+
# Not having the ability to do a dynamic 'uses' call is a real pain. To
67+
# test some new CI configuration you must set the branch in both places
68+
# below.
69+
uses: juce-framework/JUCE-utils/.github/workflows/main.yml@master
70+
with:
71+
juce-utils-branch: master
72+
nightly-targets: ${{ inputs.nightly-targets }}
73+
triggerer: ${{ inputs.triggerer && inputs.triggerer || github.event.sender.login }}
74+
cpp-std: ${{ inputs.cpp-std }}
75+
secrets: inherit
76+
deploy:
77+
if: ${{ !cancelled() && (success() || needs.build.result == 'skipped') && contains(fromJSON('["master", "develop"]'), github.ref_name) && inputs.cpp-std == '' && inputs.nightly-targets == '[]' }}
78+
needs: [build]
79+
name: Deploy
80+
uses: juce-framework/JUCE-utils/.github/workflows/deploy.yml@master
81+
secrets: inherit
82+
docs:
83+
if: ${{ !cancelled() && (success() || needs.deploy.result == 'success') && contains(fromJSON('["master", "develop"]'), github.ref_name) && inputs.cpp-std == '' && inputs.nightly-targets == '[]' }}
84+
needs: [deploy]
85+
name: Docs
86+
uses: juce-framework/JUCE-utils/.github/workflows/docs.yml@master
87+
secrets: inherit
88+
set-commit-status:
89+
if: ${{ always() && (inputs.nightly-targets == '[]') && (inputs.cpp-std == '') }}
90+
needs: [setup, build, deploy, docs]
91+
name: Set CI commit status
92+
runs-on: ubuntu-latest
93+
env:
94+
result: ${{ contains(needs.*.result, 'cancelled') && 'cancelled' || (contains(needs.*.result, 'failure') && 'failure' || 'success') }}
95+
steps:
96+
- uses: myrotvorets/set-commit-status-action@master
97+
with:
98+
token: ${{ secrets.GITHUB_TOKEN }}
99+
sha: ${{ github.sha }}
100+
status: ${{ contains(fromJSON('["cancelled", "failure"]'), env.result) && 'failure' || env.result }}
101+
context: CI
102+
description: ${{ env.result }}
103+
targetUrl: ${{ env.target_url }}
104+
notify:
105+
if: ${{ always() && !contains(needs.*.result, 'cancelled') }}
106+
needs: [setup, build, deploy, docs]
107+
name: Notify
108+
uses: juce-framework/JUCE-utils/.github/workflows/notify.yml@master
109+
with:
110+
juce-utils-branch: master
111+
triggerer: ${{ inputs.triggerer && inputs.triggerer || github.event.sender.login }}
112+
context: ${{ toJson(needs) }}
113+
secrets: inherit
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: JUCE Private GitHub Publish
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
required: true
8+
type: string
9+
description: The tag to publish ("5.4.5")
10+
11+
jobs:
12+
publish-github-release:
13+
uses: juce-framework/JUCE-utils/.github/workflows/github_publish.yml@master
14+
with:
15+
tag: ${{ inputs.tag }}
16+
secrets: inherit
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: JUCE Private Nightly Trigger
2+
on:
3+
workflow_dispatch:
4+
schedule:
5+
- cron: '0 3 * * *'
6+
env:
7+
GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
8+
TRIGGER_WORKFLOW_REF: develop
9+
jobs:
10+
juce-private-nightly-trigger:
11+
if: github.repository == 'juce-framework/JUCE-dev'
12+
name: JUCE Nightly Trigger
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4.2.2
16+
with:
17+
sparse-checkout: ./.github/workflows
18+
- env:
19+
TRIGGER_WORKFLOW_INPUTS: |
20+
{"triggerer":"Nightly Build Targets","nightly-targets":${{ vars.NIGHTLY_BUILD_TARGETS }}}
21+
run: python3 ./.github/workflows/trigger_workflow.py
22+
- if: ${{ contains(fromJSON(vars.NIGHTLY_BUILD_TARGETS), 'cpp20') }}
23+
env:
24+
TRIGGER_WORKFLOW_INPUTS: |
25+
{"triggerer":"Nightly Build C++20","cpp-std":"20"}
26+
run: python3 ./.github/workflows/trigger_workflow.py
27+
- if: ${{ contains(fromJSON(vars.NIGHTLY_BUILD_TARGETS), 'cpp23') }}
28+
env:
29+
TRIGGER_WORKFLOW_INPUTS: |
30+
{"triggerer":"Nightly Build C++23","cpp-std":"23"}
31+
run: python3 ./.github/workflows/trigger_workflow.py
32+

0 commit comments

Comments
 (0)