name: "Features - Test" on: workflow_dispatch: inputs: on_changes_only: type: boolean description: 'on_changes_only' default: false enabled: type: boolean description: 'enabled' default: true workflow_call: inputs: on_changes_only: type: boolean description: 'on_changes_only' default: false enabled: type: boolean description: 'enabled' default: true schedule: # every day at 01:00 - cron: '0 1 * * *' pull_request: push: branches: - main jobs: find-features: if: ${{ ( ( github.event_name != 'workflow_call' ) && ( github.event_name != 'workflow_dispatch' ) ) || inputs.enabled }} runs-on: ubuntu-latest name: Find feature outputs: all-features: ${{ steps.list-features.outputs.all_features }} changed-features: ${{ steps.list-features.outputs.changed_features }} steps: - uses: actions/checkout@v3 - run: | echo ${{ inputs.enabled }} echo ${{ github.event_name }} - id: list-features uses: ./.github/actions/list-changed-features-action with: path: . prepare-matrix: needs: [find-features] runs-on: ubuntu-latest outputs: features_to_test: ${{ steps.binning.outputs.binned_features }} steps: - name: "resolving features to test" id: resolve_features run: | if [ ${{ github.event_name }} == 'pull_request' ]; then echo 'features_to_test=${{ needs.find-features.outputs.changed-features }}' >> $GITHUB_OUTPUT elif [ ${{ github.event_name }} == 'push' ]; then echo 'features_to_test=${{ needs.find-features.outputs.changed-features }}' >> $GITHUB_OUTPUT elif [ ${{ github.event_name }} == 'workflow_dispatch' ]; then if [ ${{ inputs.on_changes_only }} == 'true' ]; then echo 'features_to_test=${{ needs.find-features.outputs.changed-features }}' >> $GITHUB_OUTPUT else echo 'features_to_test=${{ needs.find-features.outputs.all-features }}' >> $GITHUB_OUTPUT fi elif [ ${{ github.event_name }} == 'workflow_call' ]; then if [ ${{ inputs.on_changes_only }} == 'true' ]; then echo 'features_to_test=${{ needs.find-features.outputs.changed-features }}' >> $GITHUB_OUTPUT else echo 'features_to_test=${{ needs.find-features.outputs.all-features }}' >> $GITHUB_OUTPUT fi elif [ ${{ github.event_name }} == 'schedule' ]; then echo 'features_to_test=${{ needs.find-features.outputs.all-features }}' >> $GITHUB_OUTPUT fi - name: binning id: binning run: | cat > bin_cycle.py << EOF import sys from itertools import cycle from typing import List, Any import fileinput import json MAX_BIN_NUM=256 def cycle_baskets(items: List[Any], maxbaskets: int) -> List[List[Any]]: baskets = [[] for _ in range(min(maxbaskets, len(items)))] for item, basket in zip(items, cycle(baskets)): basket.append(item) return baskets std_input = "".join(fileinput.input()) list_binned_values = cycle_baskets(json.loads(std_input), MAX_BIN_NUM) comma_binned_values = [",".join(values) for values in list_binned_values] sys.stdout.write(json.dumps(comma_binned_values)) EOF binned_features=$(echo '${{ steps.resolve_features.outputs.features_to_test }}' | python3 bin_cycle.py) echo $binned_features echo "binned_features=$binned_features" >> $GITHUB_OUTPUT test: if: ${{ fromJson(needs.prepare-matrix.outputs.features_to_test)[0] != null }} needs: [find-features, prepare-matrix] runs-on: ubuntu-latest continue-on-error: true strategy: matrix: features: ${{ fromJson(needs.prepare-matrix.outputs.features_to_test) }} steps: - uses: actions/checkout@v3 - name: Check if the disk has to be cleaned up id: check-disk-space-requiement run: | # Array of features that require more disk storage # If there's a feature that fails during tests due to lack of disk space, add it here features_that_require_more_disk_storage=("homebrew-package" "haskell") # Array of features to test from comma separated list passed in matrix.features IFS=',' read -r -a features_to_test <<< "${{ matrix.features }}" # Check if any feature to test requires more disk storage # If so, set the output to true for feature in "${features_that_require_more_disk_storage[@]}"; do for f in "${features_to_test[@]}"; do if [ "$f" == "$feature" ]; then echo "clean_disk_space=true" >> "$GITHUB_OUTPUT" fi done done - name: Free Disk Space uses: jlumbroso/free-disk-space@main if: ${{ steps.check-disk-space-requiement.outputs.clean_disk_space == 'true' }} with: tool-cache: false docker-images: false swap-storage: false - name: "Install latest devcontainer CLI" run: npm install -g @devcontainers/cli - name: "Generating test scenarios for '${{ matrix.features }}'" run: | comma_separated_features=${{ matrix.features }} feature_array=("${comma_separated_features//,/ }") devcontainer features test -f ${feature_array[*]} --skip-autogenerated . - name: Shell Linter run: | set -e # install shellcheck comma_separated_features=${{ matrix.features }} for i in ${comma_separated_features//,/ } do shellcheck --severity=error -e SC2148 src/"$i"/*.sh done test-global: runs-on: ubuntu-latest continue-on-error: true steps: - uses: actions/checkout@v3 - name: "Install latest devcontainer CLI" run: npm install -g @devcontainers/cli - name: "Testing global scenarios" run: devcontainer features test --global-scenarios-only .