--- version: '3' vars: REPOSITORY_LIST: .cache/repository-list.txt tasks: access-token: deps: - :install:software:glab - :install:software:jq - create vars: REPO_ID: sh: glab api projects/:fullpath | jq '.id' REQUEST_DATA: '{ "name":"PROJECT_CI_ACCESS_TOKEN", "scopes":["write_repository", "read_repository"] }' TOKEN_STATUS: sh: type glab > /dev/null && glab api projects/:fullpath/access_tokens | jq -r '.[] | select(.name=="PROJECT_CI_ACCESS_TOKENX") | .id' || true run: once log: error: Failed to configure project-specific access token start: Configuring project-specific access token success: Configured project-specific access token cmds: - | curl -sSL --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" --header \ 'Content-Type:application/json' --data '{{.REQUEST_DATA}}' \ 'https://gitlab.com/api/v4/projects/{{.REPO_ID}}/access_tokens' > /dev/null status: - '[ -n "{{.TOKEN_STATUS}}" ] || ! glab api projects/:fullpath/access_tokens' branches: deps: - :install:software:glab - create vars: REPO_ID: sh: glab api projects/:fullpath | jq '.id' run: once log: error: Error encountered while setting up protected branches start: Setting up protected branches success: Set up protected branches cmds: - | glab api projects/:fullpath/protected_branches -X POST -f name=master -f code_owner_approval_required=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=main -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=main -f code_owner_approval_required=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=next -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=next -f code_owner_approval_required=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=alpha -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=alpha -f code_owner_approval_required=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=beta -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=beta -f code_owner_approval_required=true &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=protected/* -f code_owner_approval_required=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=synchronize -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=synchronize -f code_owner_approval_required=true -f allow_force_push=true &> /dev/null & if [[ '{{.REPOSITORY_TYPE}}' == 'ansible' ]]; then glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=test/linux -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=test/linux \ -f code_owner_approval_required=true -f allow_force_push=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=test/darwin -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=test/darwin \ -f code_owner_approval_required=true -f allow_force_push=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=test/windows -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=test/windows \ -f code_owner_approval_required=true -f allow_force_push=true &> /dev/null & fi if [[ '{{.REPOSITORY_TYPE}}' == 'packer' ]]; then glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=hyperv -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=hyperv \ -f code_owner_approval_required=true -f allow_force_push=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=kvm -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=kvm \ -f code_owner_approval_required=true -f allow_force_push=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=parallels -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=parallels \ -f code_owner_approval_required=true -f allow_force_push=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=virtualbox -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=virtualbox \ -f code_owner_approval_required=true -f allow_force_push=true &> /dev/null & glab api projects/:fullpath/repository/branches -X POST -f id={{.REPO_ID}} -f branch=vmware -f ref=master &> /dev/null & glab api projects/:fullpath/protected_branches -X POST -f name=vmware \ -f code_owner_approval_required=true -f allow_force_push=true &> /dev/null & fi wait create: deps: - :install:software:glab - :install:software:jq - :git:remotes vars: DESCRIPTION: sh: jq -r '.description' package.json GITLAB_GROUP: sh: jq -r '.blueprint.repository.gitlab' package.json | sed 's/https:\/\/gitlab.com\///' | sed 's!/[^/]*$!!' GITLAB_PATH: sh: jq -r '.blueprint.repository.gitlab' package.json | sed 's/https:\/\/gitlab.com\///' NAME: sh: jq -r '.blueprint.name' package.json PROJECT_TYPE: sh: if [[ $(jq -r '.private' package.json) == 'true' ]]; then echo '--private'; else echo '--public'; fi TMP: sh: mktemp run: once log: error: Encountered error while creating GitLab repository start: Ensuring GitLab repository has been created success: Ensured GitLab repository exists cmds: - cmd: | NO_PROMPT=1 glab repo create '{{.GITLAB_PATH}}' --group '{{.GITLAB_GROUP}}' \ --description '{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}' --name '{{.NAME}}' \ {{.PROJECT_TYPE}} --tag "$(jq -r '.keywords | tostring' package.json | sed 's/\[//' | sed 's/\]//')" task --list > /dev/null || (echo "ERROR: Invalid Taskfiles!" && exit 1) git add --all HUSKY=0 git commit --quiet -m "🎂 Birth" -n || true git push gitlab master ignore_error: true status: - '[ -z "$GITLAB_TOKEN" ] || (test -d .git && glab repo view "{{.GITLAB_PATH}}" > /dev/null)' preconditions: - sh: '[ "{{.DESCRIPTION}}" != "null" ]' msg: The `.description` in `package.json` must be set. - sh: '[ "{{.NAME}}" != "null" ]' msg: The `.blueprint.name` variable in `package.json` must be set. group:exec: cmds: - task: group:exec:{{if .CLI_ARGS}}cli{{else}}prompt{{end}} group:exec:cli: log: error: Failed to run group:exec logic start: Running group:exec logic success: Successfully ran group:exec logic cmds: - task git:gitlab:group:repositories -- {{index (splitList " ---- " .CLI_ARGS) 0}} - | BASE_PWD="$PWD" function execRepo() { REPO_DETAILS="$1" REPO_URL="$(echo "$REPO_DETAILS" | sed 's/ .*$//')" REPO_PATH="$(echo "$REPO_DETAILS" | sed 's/^.* //')" DIR_NAME="$(dirname "$REPO_PATH")" mkdir -p "$DIR_NAME" if [ -d "$REPO_PATH" ]; then cd "$REPO_PATH" git pull origin master || continue cd "$BASE_PWD" else git clone "$REPO_URL" "$REPO_PATH" fi .config/log info "Running bash command on $REPO_PATH" ( cd "$REPO_PATH" {{trimPrefix "'" (trimSuffix "'" (index (splitList " ---- " .CLI_ARGS) 1))}} cd "$BASE_PWD" ) .config/log success "Finished running bash command on $REPO_PATH" } cat {{.REPOSITORY_LIST}} | (while IFS= read -r REPO_DETAILS; do .config/log info "Executing logic on $REPO_DETAILS" execRepo "$REPO_DETAILS"{{if eq .GROUP_EXEC_ASYNC "true"}} &{{end}} done{{if eq .GROUP_EXEC_ASYNC "true"}} wait){{else}}){{end}} group:exec:prompt: deps: - :install:software:glab - :install:software:jq interactive: true cmds: - | GITLAB_GROUPS="$(glab api --paginate groups | jq -r '.[].full_path')" GROUP_OPTION="$(gum choose "$ENVIRONMENT_OPTIONS")" GUM_CONFIRM_MSG="Would you like to use the previously run script (i.e. .cache/gitlab-group.sh)?" if [ -f .cache/gitlab-group.sh ] && gum confirm "$GUM_CONFIRM_MSG"; then bash .cache/gitlab-group.sh else TMP="$(mktemp)" gum write --placeholder "Enter the script you would like to run including the hashbang (CTRL+D to finish)" --show-cursor-line --show-line-numbers > "$TMP" bash "$TMP" mkdir -p .cache mv "$TMP" > .cache/gitlab-group.sh fi group:repositories: deps: - :install:software:glab - :install:software:jq summary: | # Return repositories belonging to group and sub-groups Given a GitLab group path (which can include subgroups as well), this task will cycle through the group and its' subgroups and generate a list of repositories. The repositories are saved to a file located at `{{.REPOSITORY_LIST}}`. **Example specifying a group and subgroup:** `task {{.TASK}} -- megabyte-labs/ansible-roles` log: error: Encountered error while generating a list of repositories start: Generating list of repositories success: List of repositories generated cmds: - mkdir -p .cache - rm -f {{.REPOSITORY_LIST}} - task: group:repositories:loop group:repositories:loop: cmds: - glab api "groups/{{urlquery .CLI_ARGS}}" | jq -r '.projects[] | .ssh_url_to_repo + " " + .path_with_namespace' >> {{.REPOSITORY_LIST}} - | .config/log info 'Recursively acquiring repository details from subgroups' SUBGROUPS="$(glab api groups/{{urlquery .CLI_ARGS}}/subgroups | jq -r '.[] | .full_path')" if [ -n "$SUBGROUPS" ]; then echo "$SUBGROUPS" | (while IFS= read -r SUBGROUP; do task {{.TASK}} -- "$SUBGROUP" & done wait) fi ids: deps: - :install:software:glab - :install:software:jq - create log: error: Error acquiring GitLab project and group IDs start: Acquiring GitLab project and group IDs success: Saved GitLab project and group IDs to package.json cmds: - | API_RES="$(glab api projects/:fullpath)" PROJECT_ID="$(echo "$API_RES" | jq '.id')" TMP="$(mktemp)" && jq --arg projectId "$PROJECT_ID" '.blueprint.gitlab_project_id = $projectId' package.json > "$TMP" mv "$TMP" package.json GROUP_ID="$(echo "$API_RES" | jq '.namespace.id')" TMP_GROUP="$(mktemp)" && jq --arg groupId "$GROUP_ID" '.blueprint.gitlab_group_id = $groupId' package.json > "$TMP_GROUP" mv "$TMP_GROUP" package.json integrations: deps: - create run: once cmds: - task: integrations:github integrations:github: deps: - :install:software:glab - :install:software:jq log: error: Error enabling GitLab's GitHub integration start: Ensuring GitLab's GitHub integration is enabled success: GitLab's GitHub integration is enabled cmds: - glab api projects/:fullpath/integrations/github -X PUT -f token="$GITHUB_TOKEN" -f repository_url="$(jq -r '.blueprint.repository.github' package.json)" --silent status: - '[ -z "$GITLAB_TOKEN" ] || [ -z $GITHUB_TOKEN ]' mirror: deps: - :install:software:glab - :install:software:jq - :git:github:create - create vars: GITHUB_SLUG: sh: jq -r '.blueprint.repository.github' package.json | sed 's/.*\///' GITLAB_REPO_ID: sh: glab api projects/:fullpath | jq -r '.id' PUSH_MIRROR_COUNT: sh: glab api projects/:fullpath/remote_mirrors | jq '. | length' log: error: Error ensuring push/pull mirroring is enabled between GitLab and GitHub start: Ensuring push/pull mirroring from GitLab to GitHub is set up success: Push and pull mirroring from GitLab to GitHub are enabled cmds: - | if [[ "{{.PUSH_MIRROR_COUNT}}" == '0' ]]; then glab api projects/:fullpath/remote_mirrors --method POST --header "Content-Type: application/json" \ -f "url=https://{{.GITHUB_USER}}:$GITHUB_TOKEN@github.com/{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}.git" \ -f 'enabled=true' > /dev/null .config/log success 'Successfully set up push mirroring from GitLab to GitHub' fi - > curl -s -H 'Content-Type: application/json' -H "Authorization: Bearer $GITLAB_TOKEN" -X PUT --data "{\"mirror\": true, \"import_url\": \"https://{{.GITHUB_USER}}:$GITHUB_TOKEN@github.com/{{.GITHUB_ORG}}/{{.GITHUB_SLUG}}.git\"}" 'https://gitlab.com/api/v4/projects/{{.GITLAB_REPO_ID}}' > /dev/null status: - '[ -z "$GITLAB_TOKEN ] || [ -z "GITHUB_TOKEN ]' pipelines: deps: - :install:software:glab - :install:software:jq - create vars: PIPELINE_COUNT: sh: jq -r '.gitlab_pipelines | length' .variables.json log: error: Error setting up GitLab pipelines start: Ensuring GitLab pipelines are set up according to the configuration success: GitLab pipelines are set up cmds: - | PIPELINES="$(jq -r '.gitlab_pipelines' .variables.json)" PIPELINE_RES="$(glab api projects/:fullpath/pipeline_schedules)" for INDEX in {1..{{.PIPELINE_COUNT}}}; do PIPELINE_INDEX="$((INDEX - 1))" ACTIVE="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].active')" CRON="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].cron' | sed 's/"//g')" DESC="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].description')" REF="$(echo "$PIPELINES" | jq -r --arg i "$PIPELINE_INDEX" '.[$i | tonumber].ref')" if (! echo "$PIPELINE_RES" | grep "$DESC") > /dev/null; then glab api projects/:fullpath/pipeline_schedules -X POST -f active="$ACTIVE" -f description="$DESC" -f ref="$REF" \ -f cron="$CRON" -f cron_timezone='{{.TIMEZONE}}' --silent if [ "$DESC" != 'null' ]; then .config/log success "Pipeline with description of '${DESC}' successfully added"; fi else if [ "$DESC" != 'null' ]; then .config/log info "Pipeline with description of '${DESC}' already added"; fi fi done status: - '[ -z "$GITLAB_TOKEN" ]' pipelines:clear: deps: - create log: error: Error clearing GitLab pipelines start: Clearing GitLab pipelines success: Cleared GitLab pipelines cmds: - | TMP="$(mktemp)" glab api projects/:id/pipeline_schedules -X GET > "$TMP" for PIPELINE_ID in $(jq -r '.[].id' "$TMP"); do glab api projects/:fullpath/pipeline_schedules/"$PIPELINE_ID" -X DELETE done preconditions: - sh: '[ ! -z "$GITLAB_TOKEN" ]' msg: The `GITLAB_TOKEN` environment variable must be set to run this task protected:off: deps: - :install:software:glab vars: BRANCH: '{{if .BRANCH}}{{.BRANCH}}{{else}}{{.CLI_ARGS}}{{end}}' todo: figure out how to do it without deleteing the protection first cmds: - glab api projects/:fullpath/protected_branches/{{.BRANCH}} -X DELETE - glab api projects/:fullpath/protected_branches -X POST -f name={{.BRANCH}} -f allow_force_push=true > /dev/null status: - '[ -z "$GITLAB_TOKEN" ]' protected:on: deps: - :install:software:glab vars: BRANCH: '{{if .BRANCH}}{{.BRANCH}}{{else}}{{.CLI_ARGS}}{{end}}' todo: figure out how to do it without deleteing the protection first cmds: - glab api projects/:fullpath/protected_branches/{{.BRANCH}} -X DELETE - glab api projects/:fullpath/protected_branches -X POST -f name={{.BRANCH}} -f allow_force_push=false > /dev/null status: - '[ -z "$GITLAB_TOKEN" ]' ssh-keys: deps: - :install:software:glab - :install:software:jq cmds: - .config/log info 'Clearing GitLab SSH keys' - | KEY_URL='https://gitlab.com/api/v4/user/keys' KEYIDS="$(curl -sSL --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "$KEY_URL" | jq '.[].id')" for KEYID in $KEYIDS; do curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" -X DELETE "$KEY_URL/$KEYID" done - .config/log start 'Syncing SSH keys with GitLab' - | for KEY in `ls $HOME/.ssh/*.pub`; do TITLE="$(cat $KEY | sed 's/\(.*\=\) \(.*\)$/\2/')" glab ssh-key add $KEY -t "$TITLE" done - .config/log success 'Finished syncing SSH keys with GitLab' preconditions: - sh: '[ -n "$GITLAB_TOKEN" ]' msg: The GITLAB_TOKEN must be set to a personal access token. update: run: once cmds: - task: update:deps status: - '[ -z "$GITLAB_TOKEN" ] || ! type glab &> /dev/null' update:deps: deps: - access-token - branches - mirror - integrations - ids - pipelines - update:meta - wiki update:meta: deps: - :install:software:glab - :install:software:jq - create vars: DESCRIPTION: sh: jq -r '.description' package.json ISSUES_TEMPLATE: '## Summary\r\n\r\n(Summarize the bug encountered concisely)\r\n\r\n## Steps to reproduce\r\n\r\n(How one can reproduce the issue - this is very important)\r\n\r\n## Example Project\r\n\r\n(If possible, please create an example project here on GitLab.com that exhibits the problematic\r\nbehavior, and link to it here in the bug report.\r\nIf you are using an older version of GitLab, this will also determine whether the bug has been fixed\r\nin a more recent version)\r\n\r\n## What is the current bug behavior?\r\n\r\n(What actually happens)\r\n\r\n## What is the expected correct behavior?\r\n\r\n(What you should see instead)\r\n\r\n## Relevant logs and/or screenshots\r\n\r\n(Paste any relevant logs - please use code blocks (```) to format console output, logs, and code, as\r\nit is very hard to read otherwise.)\r\n\r\n## Possible fixes\r\n\r\n(If you can, link to the line of code that might be responsible for the problem)' NAME: sh: jq -r '.blueprint.name' package.json PROJECT_TYPE: sh: if [[ $(jq -r '.private' package.json) == 'true' ]]; then echo 'private'; else echo 'public'; fi TEST_COVERAGE_REGEX: sh: jq -r '.build_coverage_regex' .variables.json | sed 's/^null$//' log: error: Error ensuring GitLab metadata is up-to-date start: Ensuring GitLab metadata is up-to-date success: GitLab metadata is up-to-date cmds: - | KEYWORDS="$(jq -r '.keywords | tostring' package.json | sed 's/\[//' | sed 's/\]//' | sed 's/"//g')" PROJECT_ID="$(glab api projects/:fullpath -X PUT -f build_coverage_regex="{{.TEST_COVERAGE_REGEX}}" \ -f wiki_enabled={{.GITLAB_WIKI}} -f visibility="{{.PROJECT_TYPE}}" -f topics="$KEYWORDS" | jq '.id')" curl -s -H 'Content-Type: application/json' -H "Authorization: Bearer $GITLAB_TOKEN" -X PUT --data \ '{"description": "{{.EMOJI_START}}{{.DESCRIPTION}}{{.EMOJI_END}}", "issues_template": "{{.ISSUES_TEMPLATE}}", "name": "{{.NAME}}"}' \ "https://gitlab.com/api/v4/projects/$PROJECT_ID" > /dev/null status: - '[ -z "$GITLAB_TOKEN" ]' preconditions: - sh: '[ "{{.DESCRIPTION}}" != "null" ]' msg: The `.description` in `package.json` must be set. - sh: '[ "{{.NAME}}" != "null" ]' msg: The `.blueprint.name` variable in `package.json` must be set. wiki: deps: - :common:update:variables - :install:software:glab - :install:software:jq - create vars: DOCS_URL: sh: jq -r '.docs.link' .variables.json log: error: Failed to update GitLab wiki settings start: Setting GitLab wiki settings success: GitLab wiki settings are up-to-date cmds: - glab api projects/:fullpath/services/external-wiki -X PUT -f external_wiki_url="{{.DOCS_URL}}" --silent status: - '[ -z "$GITLAB_TOKEN" ]' preconditions: - sh: '[ "{{.DOCS_URL}}" != "null" ]' msg: The `.docs.link` variable in `.variables.json` must be set. - sh: '[ "{{.GROUP}}" != "null" ]' msg: The `.group` variable in `.variables.json` must be set.