---
version: '3'

tasks:
  create:
    deps:
      - :ci:commit:config
      - :install:software:gh
      - :install:software:jq
      - :git:remotes
    vars:
      DESCRIPTION:
        sh: jq -r '.description' package.json
      GITHUB_SLUG:
        sh: jq -r '.blueprint.repository.github' package.json | sed 's/.*\///'
      HOMEPAGE:
        sh: jq -r '.homepage' package.json
      PROJECT_TYPE:
        sh: if [[ $(jq -r '.private' package.json) == 'true' ]]; then echo '--private'; else echo '--public'; fi
    run: once
    log:
      error: Error while ensuring GitHub repository exists
      start: Checking for presence of GitHub repository and creating one if it does not exist
      success: Ensure GitHub repository is present
    cmds:
      - cmd: |
          gh repo create "{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}" --enable-wiki={{.GITHUB_WIKI}} -y --description "{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}" \
          --homepage "{{.HOMEPAGE}}" {{.PROJECT_TYPE}} > /dev/null
          task --list > /dev/null || (echo "ERROR: Invalid Taskfiles!" && exit 1)
          git add --all
          git commit --quiet -m "✨ feat(birth): Birth" -n || true
          git push github master
        ignore_error: true
    status:
      - '[ -z "$GITHUB_TOKEN" ] || (test -d .git && gh repo view "{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}" > /dev/null)'
    preconditions:
      - sh: '[ "{{.DESCRIPTION}}" != "null" ]'
        msg: The `.description` in `package.json` must be set.
      - sh: '[ "{{.GITHUB_SLUG}}" != "null" ]'
        msg: The `.name` in `package.json` must be set.
      - sh: '[ "{{.HOMEPAGE}}" != "null" ]'
        msg: The `.homepage` in `package.json` must be set.

  ids:
    deps:
      - :install:software:gh
      - :install:software:jq
      - create
    vars:
      CURRENT_PROJECT_ID:
        sh: jq -r '.blueprint.github_id' package.json
      PROJECT_ID:
        sh: gh repo view --json id | jq -r '.id'
    log:
      error: Failed to add GitHub project ID to package.json
      start: Saving GitHub project ID to package.json
      success: Added GitHub project ID to package.json
    cmds:
      - TMP="$(mktemp)" && jq --arg projectId "{{.PROJECT_ID}}" '.blueprint.github_id = $projectId' package.json > "$TMP" && mv "$TMP" package.json
    status:
      - '[[ "{{.CURRENT_PROJECT_ID}}" == "{{.PROJECT_ID}}" ]]'

  ssh-keys:
    deps:
      - :install:software:gh
      - :install:software:jq
    cmds:
      - .config/log info 'Clearing GitLab SSH keys'
      - |
        ACCEPT_HEADER="Accept: application/vnd.github+json"
        GH_KEYS_URL="https://api.github.com/user/keys"
        KEYIDS="$(curl -sSL -H "$ACCEPT_HEADER" -H "Authorization: token $GITHUB_TOKEN" "$GH_KEYS_URL" | jq '.[].id')"
        for KEYID in $KEYIDS; do
          curl -H "$ACCEPT_HEADER" -H "Authorization: token $GITHUB_TOKEN" -X DELETE "$GH_KEYS_URL/$KEYID"
        done
      - .config/log start 'Syncing SSH keys with GitHub'
      - |
        for KEY in `ls $HOME/.ssh/*.pub`; do
          TITLE="$(cat $KEY | sed 's/\(.*\=\) \(.*\)$/\2/')"
          gh ssh-key add $KEY -t "$TITLE"
        done
      - .config/log success 'Finished syncing SSH keys with GitHub'
    preconditions:
      - sh: '[ -n "$GITHUB_TOKEN" ]'
        msg: The GITHUB_TOKEN must be set to a personal access token.

  update:
    run: once
    cmds:
      - task: update:deps
    status:
      - '[ -z "$GITHUB_TOKEN" ]'

  update:deps:
    deps:
      - update:meta
      - ids
      - variables

  update:meta:
    deps:
      - :install:software:gh
      - :install:software:jq
      - create
    vars:
      DESCRIPTION:
        sh: jq -r '.description' package.json
      GITHUB_SLUG:
        sh: jq -r '.blueprint.repository.github' package.json | sed 's/.*\///'
      HOMEPAGE:
        sh: jq -r '.homepage' package.json
      PRIVATE:
        sh: jq -r '.private' package.json | sed 's/null/false/'
    log:
      error: Error while updating GitHub repository metadata
      start: Updating GitHub project metadata
      success: Updated GitHub repository metadata
    cmds:
      - |
        OPTIONAL_TAGS="$(jq '.keywords' .config/common-keywords.json)"
        TOPICS="$(jq '.keywords' package.json | sed 's/null/[]/')"
        TOPICS_LENGTH="$(jq -r '.keywords | length' package.json)"
        if [ ! -z "$GITHUB_TOKEN" ]; then
          gh api -X PATCH repos/{{.GITHUB_ORG}}/{{.GITHUB_SLUG}} -f description="{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}" -f homepage="{{.HOMEPAGE}}" \
            -f has_issues={{.GITHUB_ISSUES}} -f has_wiki={{.GITHUB_WIKI}} -f private="{{.PRIVATE}}" --silent
          .config/log success 'Ensured GitHub metadata is up-to-date'
          RESULT="$TOPICS"
          if [ "$TOPICS_LENGTH" -gt 20 ]; then
            function updateList() {
              REMOVE_KEY="$(jq -n --argjson optional "$OPTIONAL_TAGS" '$optional['"$1"']')"
              RESULT="$(jq -n --argjson remove "$REMOVE_KEY" --argjson jq "$RESULT" '$jq | del(.[] | select(. == $remove))')"
            }
            LOOP_COUNT="$((TOPICS_LENGTH-20))"
            for i in $(seq "$LOOP_COUNT"); do
              updateList "$i"
            done
          fi
          MINIMIZED_TOPICS="$(jq -n --argjson tags "$RESULT" '$tags | .[]' | xargs | sed 's/ /","/g' | sed 's/^/"/' | sed 's/$/"/')"
          if [[ "$MINIMIZED_TOPICS" != '""' ]]; then
            curl -s -X PUT -H "Accept: application/vnd.github.mercy-preview+json" -u "{{.GITHUB_ORG}}:$GITHUB_TOKEN" \
              'https://api.github.com/repos/{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}/topics' -d '{"names":['"$MINIMIZED_TOPICS"']}' > /dev/null
            .config/log success 'Updated GitHub topics successfully'
          fi
        else
          .config/log warn 'The `GITHUB_TOKEN` environment variable is not set so the GitHub repository cannot be updated via the API.'
        fi
    sources:
      - .config/common-keywords.json
      - .variables.json
      - package.json
    preconditions:
      - sh: '[ "{{.DESCRIPTION}}" != "null" ]'
        msg: The `.description` in `package.json` must be set.
      - sh: '[ "{{.HOMEPAGE}}" != "null" ]'
        msg: The `.homepage` in `package.json` must be set.

  variables:
    deps:
      - :install:software:gh
      - create
    log:
      error: Error setting GitHub Actions Ansible Galaxy token
      start: Setting GitHub Actions Ansible Galaxy token
      success: GitHub Actions Ansible Galaxy token set
    cmds:
      - gh secret set ANSIBLE_GALAXY_TOKEN -b "$ANSIBLE_GALAXY_TOKEN"
    status:
      - '[ -z "$GITHUB_TOKEN" ] || [ -z "$ANSIBLE_GALAXY_TOKEN" ] || [ "{{.REPOSITORY_TYPE}}" != "ansible" ]'
