Merge branch 'cicd' into 'main'

Cicd

See merge request Thoscellen/Wallset!2
This commit is contained in:
Simon 2023-05-08 14:09:30 +00:00
commit 5c4b1e769c
9 changed files with 130 additions and 46 deletions

View File

@ -6,39 +6,71 @@ stages:
- Release - Release
variables: variables:
ENTRY_FOLDER: "test" ENTRY_FOLDER: "test" # test directory for testing CI/CD, or assets directory for normal operations
RELEASE_VERSION: v0.$CI_PIPELINE_IID RELEASE_VERSION: v0.$CI_PIPELINE_IID
PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${PACKAGE_NAME}/${RELEASE_VERSION}" PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/${PACKAGE_NAME}/${RELEASE_VERSION}"
# TODO: to reenable later
# Jobs from here run on Merge Requests as prerequisite for merging. # Jobs from here run on Merge Requests as prerequisite for merging.
.gen-manifest-job: &gen-manifest .manifest-job: &manifest
stage: Manifest stage: Manifest
rules: rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes: changes:
# TODO: refacto this (as Reference or something else) # TODO: refacto this (as Reference or something else)
- test/${PACKAGE_NAME}/* - ${ENTRY_FOLDER}/${PACKAGE_NAME}/*
script: script:
- echo generating manifest for ${ENTRY_FOLDER}/${PACKAGE_NAME} - echo generating manifest for ${ENTRY_FOLDER}/${PACKAGE_NAME}
gen-manifest-job/valid_set: # manifest-job/valid_set:
variables: # variables:
PACKAGE_NAME: "valid_set" # PACKAGE_NAME: "valid_set"
<<: *gen-manifest # <<: *gen-manifest
.check-content-job: &check-content .test-images-job: &test-images
stage: Test stage: Test
image: python:latest
rules: rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes: changes:
- ${ENTRY_FOLDER}/${PACKAGE_NAME}/* - ${ENTRY_FOLDER}/${PACKAGE_NAME}/*
script: script:
- echo testing ${ENTRY_FOLDER}/${PACKAGE_NAME} - pip install -U pytest pillow iteration_utilities
- python -m pytest src/test_images_job/test_wpp.py --tb=line -rA --color=yes --code-highlight=yes -q
allow_failure: true
check-content-job/valid_set: test-images-job/valid_set:
variables: variables:
PACKAGE_NAME: "valid_set" PACKAGE_NAME: "valid_set"
<<: *check-content <<: *test-images
test-images-job/missing_tag_set:
variables:
PACKAGE_NAME: "missing_tag_set"
<<: *test-images
.test-manifest-job: &test-manifest
stage: Test
image: node:latest
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
changes:
- ${ENTRY_FOLDER}/${PACKAGE_NAME}/*
script:
- cd src/test_manifest_job
- npm install ajv ajv-errors mocha mocha-steps chai
- cd ../..
- node src/test_manifest_job/node_modules/mocha/bin/_mocha --require mocha-steps --colors src/test_manifest_job/wpp_checker.js
test-manifest-job/valid_set:
variables:
PACKAGE_NAME: "valid_set"
<<: *test-manifest
test-manifest-job/missing_tag_set:
variables:
PACKAGE_NAME: "missing_tag_set"
<<: *test-manifest
# Jobs from here run Merged_results or Push/Merge Commits to the main branch. Tag is created on release so no run with tag creation # Jobs from here run Merged_results or Push/Merge Commits to the main branch. Tag is created on release so no run with tag creation
.bundle-job: &bundle .bundle-job: &bundle
@ -63,6 +95,11 @@ bundle-job/valid_set:
PACKAGE_NAME: "valid_set" PACKAGE_NAME: "valid_set"
<<: *bundle <<: *bundle
bundle-job/missing_tag_set:
variables:
PACKAGE_NAME: "missing_tag_set"
<<: *bundle
.upload-job: &upload .upload-job: &upload
stage: Distribute stage: Distribute
image: curlimages/curl:latest image: curlimages/curl:latest
@ -78,12 +115,19 @@ bundle-job/valid_set:
--header "JOB-TOKEN: ${CI_JOB_TOKEN}" \ --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
--upload-file ${PACKAGE_NAME}.zip "${PACKAGE_REGISTRY_URL}/${PACKAGE_NAME}.zip?select=package_file" --upload-file ${PACKAGE_NAME}.zip "${PACKAGE_REGISTRY_URL}/${PACKAGE_NAME}.zip?select=package_file"
# upload-job/valid_set: upload-job/valid_set:
# needs: needs:
# - bundle-job/valid_set - bundle-job/valid_set
# variables: variables:
# PACKAGE_NAME: "valid_set" PACKAGE_NAME: "valid_set"
# <<: *upload <<: *upload
upload-job/missing_tag_set:
needs:
- bundle-job/missing_tag_set
variables:
PACKAGE_NAME: "missing_tag_set"
<<: *upload
.release-job: &release .release-job: &release
stage: Release stage: Release
@ -105,9 +149,17 @@ bundle-job/valid_set:
links: links:
- name: ${PACKAGE_NAME} - name: ${PACKAGE_NAME}
url: "${PACKAGE_REGISTRY_URL}/${PACKAGE_NAME}.zip" url: "${PACKAGE_REGISTRY_URL}/${PACKAGE_NAME}.zip"
# release-job/valid_set:
# needs: release-job/valid_set:
# - upload-job/valid_set needs:
# variables: - upload-job/valid_set
# PACKAGE_NAME: "valid_set" variables:
# <<: *release PACKAGE_NAME: "valid_set"
<<: *release
release-job/missing_tag_set:
needs:
- upload-job/missing_tag_set
variables:
PACKAGE_NAME: "missing_tag_set"
<<: *release

View File

@ -46,8 +46,8 @@ def validate_brightness_image(working_path, theme_config, high_light, image_list
@pytest.fixture @pytest.fixture
def working_path(): def working_path():
# get the global variables containing gitlab-given project slug. # get the global variables containing gitlab-given project slug.
project_slug = os.environ["WPP_SLUG"] project_slug = os.environ["PACKAGE_NAME"]
root_folder = os.environ["WPP_ROOT"] root_folder = os.environ["ENTRY_FOLDER"]
working_path = Path(root_folder, project_slug) working_path = Path(root_folder, project_slug)
if not working_path.is_dir(): if not working_path.is_dir():
raise FileNotFoundError(f"No project found for the given {working_path}.") raise FileNotFoundError(f"No project found for the given {working_path}.")
@ -76,7 +76,6 @@ def test_image_size(working_path, manifest):
assert w >= h, "✖ Image orientation is portrait (must be landscape or square)" assert w >= h, "✖ Image orientation is portrait (must be landscape or square)"
# print(f"✔ Images are big enough ({w}×{h}) and landscape.") # print(f"✔ Images are big enough ({w}×{h}) and landscape.")
def test_overlapping_images(manifest): def test_overlapping_images(manifest):
jointed_lists = manifest.get("dayImageList") jointed_lists = manifest.get("dayImageList")
jointed_lists.extend(manifest.get("nightImageList")) jointed_lists.extend(manifest.get("nightImageList"))

View File

@ -3,21 +3,21 @@ const path = require("path");
const { env, exit } = require("process"); const { env, exit } = require("process");
const expect = require("chai").expect; const expect = require("chai").expect;
const Ajv = require("ajv").default; const Ajv = require("ajv").default;
const ajv = new Ajv({allErrors: true}); const ajv = new Ajv({ allErrors: true });
require("ajv-errors")(ajv); require("ajv-errors")(ajv);
//let root, slug; //let root, slug;
//let workingDirectory = path.join(root, slug); //let workingDirectory = path.join(root, slug);
//console.log(`👷‍♂️ Working with ${slug} slug.`); //console.log(`👷‍♂️ Working with ${slug} slug.`);
const themeSchemaFile = ".gitlab/node_job/json_theme_schema.jsonc"; const themeSchemaFile = "src/test_manifest_job/json_theme_schema.jsonc";
let wppManifest; let wppManifest;
let validator; let validator;
let files; let files;
function leftOuterJoin(leftArray, rightArray) { function leftOuterJoin(leftArray, rightArray) {
return leftArray.filter(function(el) { return leftArray.filter(function (el) {
return this.indexOf(el) < 0; return this.indexOf(el) < 0;
}, rightArray); }, rightArray);
} }
@ -25,7 +25,7 @@ function flatReferences(wppManifest) {
allImageIds = [ allImageIds = [
wppManifest.dayHighlight, wppManifest.dayHighlight,
wppManifest.nightHighlight, wppManifest.nightHighlight,
...wppManifest.dayImageList, ...wppManifest.dayImageList,
...wppManifest.nightImageList, ...wppManifest.nightImageList,
...(wppManifest.sunsetImageList || []), ...(wppManifest.sunsetImageList || []),
...(wppManifest.sunriseImageList || []) ...(wppManifest.sunriseImageList || [])
@ -35,42 +35,42 @@ function flatReferences(wppManifest) {
}); });
} }
describe('Mandatory Checks', function() { describe('Mandatory Checks', function () {
before(function() { before(function () {
slug = env.WPP_SLUG; slug = env.PACKAGE_NAME;
expect(slug).to.be.a("string").that.is.not.empty; expect(slug).to.be.a("string").that.is.not.empty;
root = env.WPP_ROOT; root = env.ENTRY_FOLDER;
expect(root).to.be.a("string").that.is.not.empty; expect(root).to.be.a("string").that.is.not.empty;
workingDirectory = path.join(root, slug); workingDirectory = path.join(root, slug);
files = fs.readdirSync(workingDirectory); files = fs.readdirSync(workingDirectory);
expect(files).to.be.an('array').that.is.not.empty; expect(files).to.be.an('array').that.is.not.empty;
validator = ajv.compile(JSON.parse(fs.readFileSync(themeSchemaFile, 'utf8'))); validator = ajv.compile(JSON.parse(fs.readFileSync(themeSchemaFile, 'utf8')));
}); });
step('Manifest is an existing json file', function() { step('Manifest is an existing json file', function () {
wppManifest = JSON.parse(fs.readFileSync(path.join(workingDirectory, "theme.json"), "utf8")); wppManifest = JSON.parse(fs.readFileSync(path.join(workingDirectory, "theme.json"), "utf8"));
}); });
step('Manifest passes the schema', function() { step('Manifest passes the schema', function () {
const isValid = validator(wppManifest); const isValid = validator(wppManifest);
if(!isValid) expect.fail(`\n\t${validator.errors.map(el => {return el.message;}).join('\n\t• ')}`); if (!isValid) expect.fail(`\n\t${validator.errors.map(el => { return el.message; }).join('\n\t• ')}`);
}); });
step('There are no missing files', function() { step('There are no missing files', function () {
let references = flatReferences(wppManifest); let references = flatReferences(wppManifest);
references.push("theme.json"); references.push("theme.json");
missings = leftOuterJoin(references, files); missings = leftOuterJoin(references, files);
expect(missings, expect(missings,
`The following reference${(missings.length > 1)? "s": ""} from theme.json ${(missings.length > 1)? "are": "is"} missing in the pack. Consider adding ${(missings.length > 1)? "them": " it"} to the pack or removing the reference${(missings.length > 1)? "s": ""} from the theme.json:\n\t${missings.join('\n\t• ')}\n` `The following reference${(missings.length > 1) ? "s" : ""} from theme.json ${(missings.length > 1) ? "are" : "is"} missing in the pack. Consider adding ${(missings.length > 1) ? "them" : " it"} to the pack or removing the reference${(missings.length > 1) ? "s" : ""} from the theme.json:\n\t${missings.join('\n\t• ')}\n`
).to.be.lengthOf(0, ); ).to.be.lengthOf(0,);
}); });
step('There are no orphan files', function() { step('There are no orphan files', function () {
let references = flatReferences(wppManifest); let references = flatReferences(wppManifest);
orphans = leftOuterJoin(files.filter(x => x !== "theme.json"), references); orphans = leftOuterJoin(files.filter(x => x !== "theme.json"), references);
expect(orphans, expect(orphans,
`The following orphan file${(orphans.length > 1)? "s are": " is"} not referenced in this theme.json. Consider removing the file${(orphans.length > 1)? "s": ""} or referencing ${(orphans.length > 1)? "them": "it"} in the theme.json:\n\t${orphans.join('\n\t• ')}\n` `The following orphan file${(orphans.length > 1) ? "s are" : " is"} not referenced in this theme.json. Consider removing the file${(orphans.length > 1) ? "s" : ""} or referencing ${(orphans.length > 1) ? "them" : "it"} in the theme.json:\n\t${orphans.join('\n\t• ')}\n`
).to.be.lengthOf(0); ).to.be.lengthOf(0);
}); });
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

View File

@ -0,0 +1,14 @@
{
"imageFilename": "bl3_landscape_*.jpg",
"imageCredits": "© Gearbox",
"displayName": "",
"dayImageList": [
2
],
"sunsetImageList": [
2
],
"nightImageList": [
3
]
}

19
test/valid_set/theme.json Normal file
View File

@ -0,0 +1,19 @@
{
"imageFilename": "bl2_eridum_badlands_*.jpg",
"imageCredits": "Gearbox",
"displayName": "",
"dayHighlight": 1,
"nightHighlight": 3,
"sunriseImageList": [
4
],
"dayImageList": [
1
],
"sunsetImageList": [
2
],
"nightImageList": [
3
]
}