name: build-and-test
on:
  push:
    branches: [ main ]
    tags:
      - 'v[0-9]+.[0-9]+.[0-9]+*'
  pull_request:
env:
  TEST_RESULTS: testbed/tests/results/junit/results.xml

jobs:
  windows-test:
    runs-on: windows-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
        shell: bash
      - name: Cache Go
        uses: actions/cache@v2
        env:
          cache-name: cache-go-modules
        with:
          path: |
            \Users\runneradmin\go\pkg\mod
            %LocalAppData%\go-build
          key: go-pkg-mod-${{ runner.os }}-${{ hashFiles('./go.mod', '**/go.sum') }}
      - name: Run Unit tests
        run: go test ./...
      - name: GitHub Issue Generator
        if: ${{ failure() && github.ref == 'ref/head/main' }}
        run: |
          go run cmd/issuegenerator/main.go $TEST_RESULTS
  setup-environment:
    runs-on: ubuntu-latest
    outputs:
      matrix: ${{ steps.splitloadtest.outputs.matrix }}
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
      - name: Cache Go
        id: module-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-go-modules
        with:
          path: |
            /home/runner/go/pkg/mod
            /home/runner/.cache/go-build
          key: go-pkg-mod-${{ runner.os }}-${{ hashFiles('**/go.mod', '**/go.sum') }}
      - name: Install dependencies
        if: steps.module-cache.outputs.cache-hit != 'true'
        run: |
          make gomoddownload
          make gotestinstall
      - name: Cache Tools
        id: tool-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-tool-binaries
        with:
          path: /home/runner/go/bin
          key: tools-${{ runner.os }}-${{ hashFiles('./internal/tools/go.mod', './cmd/mdatagen/go.mod', './cmd/mdatagen/*.go') }}
      - name: Install Tools
        if: steps.tool-cache.outputs.cache-hit != 'true'
        run: make install-tools
      - name: Split Loadtest Jobs
        id: splitloadtest
        run: ./.github/workflows/scripts/setup_load_tests.sh
  lint:
    runs-on: ubuntu-latest
    needs: [setup-environment]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
      - name: Cache Go
        id: module-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-go-modules
        with:
          path: |
            /home/runner/go/pkg/mod
            /home/runner/.cache/go-build
          key: go-pkg-mod-${{ runner.os }}-${{ hashFiles('**/go.mod', '**/go.sum') }}
      - name: Cache Tools
        id: tool-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-tool-binaries
        with:
          path: /home/runner/go/bin
          key: tools-${{ runner.os }}-${{ hashFiles('./internal/tools/go.mod', './cmd/mdatagen/go.mod', './cmd/mdatagen/*.go') }}
      - name: Lint
        run: make -j5 checklicense misspell checkdoc goimpi golint
      - name: Gen Metadata
        run: |
          make genmdata
          git diff --exit-code || (echo 'Generated code is out of date, please run "make genmdata" and commit the changes in this PR.' && exit 1)
      - name: Gen Pdata
        run: |
          make genpdata
          git diff --exit-code || (echo 'Generated code is out of date, please run "make genpdata" and commit the changes in this PR.' && exit 1)
  unittest:
    runs-on: ubuntu-latest
    needs: [setup-environment]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
      - name: Cache Go
        id: module-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-go-modules
        with:
          path: |
            /home/runner/go/pkg/mod
            /home/runner/.cache/go-build
          key: go-pkg-mod-${{ runner.os }}-${{ hashFiles('**/go.mod', '**/go.sum') }}
      - name: Cache Tools
        id: tool-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-tool-binaries
        with:
          path: /home/runner/go/bin
          key: tools-${{ runner.os }}-${{ hashFiles('./internal/tools/go.mod', './cmd/mdatagen/go.mod', './cmd/mdatagen/*.go') }}
      - name: Run Unit Tests
        run: |
          mkdir -p test-results/junit
          trap "go-junit-report -set-exit-code < test-results/junit/unittests.out > test-results/junit/unittests.xml" EXIT
          # some hostmetrics scraping tests require access to /proc.
          sudo make gotest | tee test-results/junit/unittests.out
      - name: Upload Unit Test Results
        if: always()
        uses: actions/upload-artifact@v2.2.4
        with:
          name: unittests-results
          path: test-results/junit/unittests.xml
  cross-compile:
    runs-on: ubuntu-latest
    needs: [setup-environment]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
      - name: Cache Go
        id: module-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-go-modules
        with:
          path: |
            /home/runner/go/pkg/mod
            /home/runner/.cache/go-build
          key: go-pkg-mod-${{ runner.os }}-${{ hashFiles('**/go.mod', '**/go.sum') }}
      - name: Build Collector for All Architectures
        run: make binaries-all-sys
      - name: Create Collector Binaries Archive
        run: tar -cvf bin.tar ./bin
      - name: Upload Collector Binaries
        uses: actions/upload-artifact@v2.2.4
        with:
          name: collector-binaries
          path: ./bin.tar
  loadtest:
    runs-on: ubuntu-latest
    needs: [setup-environment]
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.setup-environment.outputs.matrix) }}
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
      - name: Cache Go
        id: module-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-go-modules
        with:
          path: |
            /home/runner/go/pkg/mod
            /home/runner/.cache/go-build
          key: go-pkg-mod-${{ runner.os }}-${{ hashFiles('**/go.mod', '**/go.sum') }}
      - name: Cache Tools
        id: tool-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-tool-binaries
        with:
          path: /home/runner/go/bin
          key: tools-${{ runner.os }}-${{ hashFiles('./internal/tools/go.mod', './cmd/mdatagen/go.mod', './cmd/mdatagen/*.go') }}
      - run: mkdir -p results && touch results/TESTRESULTS.md
      - name: Loadtest
        run: make testbed-loadtest
        env:
          TEST_ARGS: "-test.run=${{ matrix.test }}"
      - name: Create Test Result Archive # some test results have invalid characters
        if: ${{ failure() || success() }}
        continue-on-error: true
        run: tar -cvf test_results.tar testbed/tests/results
      - name: Upload Test Results
        if: ${{ failure() || success() }}
        continue-on-error: true
        uses: actions/upload-artifact@v2.2.4
        with:
          name: test-results
          path: test_results.tar
      - name: GitHub Issue Generator
        if: ${{ failure() && github.ref == 'ref/head/main' }}
        run: |
          go run cmd/issuegenerator/main.go $TEST_RESULTS
  correctness-traces:
    runs-on: ubuntu-latest
    needs: [setup-environment]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
      - name: Cache Go
        id: module-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-go-modules
        with:
          path: |
            /home/runner/go/pkg/mod
            /home/runner/.cache/go-build
          key: go-pkg-mod-${{ runner.os }}-${{ hashFiles('**/go.mod', '**/go.sum') }}
      - name: Cache Tools
        id: tool-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-tool-binaries
        with:
          path: /home/runner/go/bin
          key: tools-${{ runner.os }}-${{ hashFiles('./internal/tools/go.mod', './cmd/mdatagen/go.mod', './cmd/mdatagen/*.go') }}
      - name: Correctness
        run: make testbed-correctness-traces
      - name: GitHub Issue Generator
        if: ${{ failure() && github.ref == 'ref/head/main' }}
        run: |
          go run cmd/issuegenerator/main.go $TEST_RESULTS
  correctness-metrics:
    runs-on: ubuntu-latest
    needs: [setup-environment]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
      - name: Cache Go
        id: module-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-go-modules
        with:
          path: |
            /home/runner/go/pkg/mod
            /home/runner/.cache/go-build
          key: go-pkg-mod-${{ runner.os }}-${{ hashFiles('**/go.mod', '**/go.sum') }}
      - name: Cache Tools
        id: tool-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-tool-binaries
        with:
          path: /home/runner/go/bin
          key: tools-${{ runner.os }}-${{ hashFiles('./internal/tools/go.mod', './cmd/mdatagen/go.mod', './cmd/mdatagen/*.go') }}
      - name: Correctness
        run: make testbed-correctness-metrics
      - name: GitHub Issue Generator
        if: ${{ failure() && github.ref == 'ref/head/main' }}
        run: |
          go run cmd/issuegenerator/main.go $TEST_RESULTS
  build-package:
    runs-on: ubuntu-latest
    needs: [cross-compile]
    strategy:
      fail-fast: false
      matrix:
        package_type: ["deb", "rpm"]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
          mkdir bin/
      - name: Install Ruby
        uses: actions/setup-ruby@v1
        with:
          ruby-version: '2.6'
      - name: Install fpm
        run: gem install --no-document fpm -v 1.11.0
      - name: Cache Tools
        id: tool-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-tool-binaries
        with:
          path: /home/runner/go/bin
          key: tools-${{ runner.os }}-${{ hashFiles('./internal/tools/go.mod', './cmd/mdatagen/go.mod', './cmd/mdatagen/*.go') }}
      - name: Download Collector Binaries
        uses: actions/download-artifact@v1
        with:
          name: collector-binaries
      - name: Extract Binaries Archive
        run: tar -xvf collector-binaries/bin.tar
      - name: Set Release Tag
        id: github_tag
        run: ./.github/workflows/scripts/set_release_tag.sh
      - name: Build ${{ matrix.package_type }} amd64 package
        run: ./internal/buildscripts/packaging/fpm/${{ matrix.package_type }}/build.sh "${{ steps.github_tag.outputs.tag }}" "amd64" "./dist/"
      - name: Build ${{ matrix.package_type }} arm64 package
        run: ./internal/buildscripts/packaging/fpm/${{ matrix.package_type }}/build.sh "${{ steps.github_tag.outputs.tag }}" "arm64" "./dist/"
      - name: Test ${{ matrix.package_type }} package
        run: |
          if [[ "${{ matrix.package_type }}" = "deb" ]]; then
              ./internal/buildscripts/packaging/fpm/test.sh dist/otel-collector*amd64.deb
          else
              ./internal/buildscripts/packaging/fpm/test.sh dist/otel-collector*x86_64.rpm
          fi
      - name: Upload Packages
        uses: actions/upload-artifact@v2.2.4
        with:
          name: build-packages
          path: ./dist
  windows-msi:
    runs-on: windows-latest
    needs: [cross-compile]
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
          mkdir bin/
      - name: Download Binaries
        uses: actions/download-artifact@v1
        with:
          name: collector-binaries
      - name: Extract Binaries Archive
        run: tar -xvf collector-binaries/bin.tar
      - name: Install Wix Toolset
        run: .\internal\buildscripts\packaging\msi\make.ps1 Install-Tools
      - name: Build MSI
        run: |
          $Version = if ($env:GITHUB_REF -match '^refs/tags/(\d+\.\d+\.\d+)') { $Matches[1] } else { "0.0.1" }
          .\internal\buildscripts\packaging\msi\make.ps1 New-MSI -Version $Version
      - name: Validate MSI
        run: .\internal\buildscripts\packaging\msi\make.ps1 Confirm-MSI
      - name: Upload MSI
        uses: actions/upload-artifact@v2.2.4
        with:
          name: msi-binaries
          path: ./dist
  publish-dev:
    runs-on: ubuntu-latest
    needs: [build-package, windows-msi]
    if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')) && github.repository == 'open-telemetry/opentelemetry-collector'
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
          mkdir bin/ dist/
      - name: Cache Tools
        id: tool-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-tool-binaries
        with:
          path: /home/runner/go/bin
          key: tools-${{ runner.os }}-${{ hashFiles('./internal/tools/go.mod', './cmd/mdatagen/go.mod', './cmd/mdatagen/*.go') }}
      - name: Download Binaries
        uses: actions/download-artifact@v1
        with:
          name: collector-binaries
      - name: Extract Binaries Archive
        run: tar -xvf collector-binaries/bin.tar
      - name: Download Packages
        uses: actions/download-artifact@v1
        with:
          name: build-packages
          path: ./dist
      - name: Download MSI Packages
        uses: actions/download-artifact@v1
        with:
          name: msi-binaries
          path: ./dist
      - name: Add Permissions to Tool Binaries
        run: chmod -R +x ./dist
      - name: Verify Distribution Files Exist
        id: check
        run: ./.github/workflows/scripts/verify-dist-files-exist.sh
      - name: Build Docker Image
        if: steps.check.outputs.passed == 'true'
        run: |
            make docker-otelcol
            docker tag otelcol:latest otel/opentelemetry-collector-dev:$GITHUB_SHA
            docker tag otelcol:latest otel/opentelemetry-collector-dev:latest
      - name: Push Docker Image
        if: steps.check.outputs.passed == 'true'
        run: |
            docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
            docker push otel/opentelemetry-collector-dev:$GITHUB_SHA
            docker push otel/opentelemetry-collector-dev:latest
        env:
          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME}}
          DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD}}
  publish-stable:
    runs-on: ubuntu-latest
    needs: [build-package, windows-msi]
    if: startsWith(github.ref, 'refs/tags/') && github.repository == 'open-telemetry/opentelemetry-collector'
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v2
      - name: Setup Go
        uses: actions/setup-go@v2.1.3
        with:
          go-version: 1.16
      - name: Setup Go Environment
        run: |
          echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
          echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
          mkdir bin/ dist/
      - name: Cache Tools
        id: tool-cache
        uses: actions/cache@v2
        env:
          cache-name: cache-tool-binaries
        with:
          path: /home/runner/go/bin
          key: tools-${{ runner.os }}-${{ hashFiles('./internal/tools/go.mod', './cmd/mdatagen/go.mod', './cmd/mdatagen/*.go') }}
      - name: Download Binaries
        uses: actions/download-artifact@v1
        with:
          name: collector-binaries
      - name: Extract Binaries Archive
        run: tar -xvf collector-binaries/bin.tar
      - name: Download Packages
        uses: actions/download-artifact@v1
        with:
          name: build-packages
          path: ./dist
      - name: Download MSI Packages
        uses: actions/download-artifact@v1
        with:
          name: msi-binaries
          path: ./dist
      - name: Add Permissions to Tool Binaries
        run: chmod -R +x ./dist
      - name: Verify Distribution Files Exist
        id: check
        run: ./.github/workflows/scripts/verify-dist-files-exist.sh
      - name: Set Release Tag
        id: github_tag
        run: ./.github/workflows/scripts/set_release_tag.sh
      - name: Build Docker Image
        if: steps.check.outputs.passed == 'true'
        run: |
            make docker-otelcol
            docker tag otelcol:latest otel/opentelemetry-collector:$RELEASE_TAG
            docker tag otelcol:latest otel/opentelemetry-collector:latest
        env:
          RELEASE_TAG: ${{ steps.github_tag.outputs.tag }}
      - name: Push Docker Image
        if: steps.check.outputs.passed == 'true'
        run: |
            docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
            docker push otel/opentelemetry-collector:$RELEASE_TAG
            docker push otel/opentelemetry-collector:latest
        env:
          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME}}
          DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD}}
          RELEASE_TAG: ${{ steps.github_tag.outputs.tag }}
      - name: Create Github Release
        if: steps.check.outputs.passed == 'true'
        run: |
          cp bin/* dist/
          cd dist && shasum -a 256 * > checksums.txt
          ghr -t $GITHUB_TOKEN -u "GitHub Action" -r opentelemetry-collector --replace $RELEASE_TAG dist/
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          RELEASE_TAG: ${{ steps.github_tag.outputs.tag }}
