diff --git a/third_party/AndreasAugustin/actions-template-sync/.all-contributorsrc b/third_party/AndreasAugustin/actions-template-sync/.all-contributorsrc new file mode 100644 index 00000000..cdb0efa4 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.all-contributorsrc @@ -0,0 +1,399 @@ +{ + "files": [ + "README.md" + ], + "imageSize": 100, + "commit": false, + "contributors": [ + { + "login": "AndreasAugustin", + "name": "andy Augustin", + "avatar_url": "https://avatars0.githubusercontent.com/u/8027933?v=4", + "profile": "https://github.com/AndreasAugustin", + "contributions": [ + "doc", + "code", + "review", + "security", + "ideas", + "question", + "example", + "content", + "blog", + "maintenance", + "infra", + "platform", + "test" + ] + }, + { + "login": "pattacini", + "name": "Ugo Pattacini", + "avatar_url": "https://avatars.githubusercontent.com/u/3738070?v=4", + "profile": "https://www.iit.it/people/ugo-pattacini", + "contributions": [ + "doc" + ] + }, + { + "login": "jg-rivera", + "name": "Jose Gabrielle Rivera", + "avatar_url": "https://avatars.githubusercontent.com/u/27613092?v=4", + "profile": "https://github.com/jg-rivera", + "contributions": [ + "code" + ] + }, + { + "login": "pdrittenhouse", + "name": "P.D. Rittenhouse", + "avatar_url": "https://avatars.githubusercontent.com/u/1556730?v=4", + "profile": "http://pdrittenhouse.com", + "contributions": [ + "ideas" + ] + }, + { + "login": "Daniel-Boll", + "name": "Daniel Boll", + "avatar_url": "https://avatars.githubusercontent.com/u/43689101?v=4", + "profile": "https://github.com/Daniel-Boll", + "contributions": [ + "bug" + ] + }, + { + "login": "albertschwarzkopf", + "name": "albertschwarzkopf", + "avatar_url": "https://avatars.githubusercontent.com/u/35684914?v=4", + "profile": "https://github.com/albertschwarzkopf", + "contributions": [ + "ideas" + ] + }, + { + "login": "akulpillai", + "name": "Akul Pillai", + "avatar_url": "https://avatars.githubusercontent.com/u/32793567?v=4", + "profile": "http://akulpillai.com", + "contributions": [ + "security" + ] + }, + { + "login": "steveizzle", + "name": "Stefan Riembauer", + "avatar_url": "https://avatars.githubusercontent.com/u/45331237?v=4", + "profile": "https://github.com/steveizzle", + "contributions": [ + "ideas" + ] + }, + { + "login": "fabriziocacicia", + "name": "Fabrizio Cacicia", + "avatar_url": "https://avatars.githubusercontent.com/u/7525888?v=4", + "profile": "http://fabriziocacicia.com", + "contributions": [ + "security", + "bug" + ] + }, + { + "login": "JTunis", + "name": "Justin Tunis", + "avatar_url": "https://avatars.githubusercontent.com/u/11543636?v=4", + "profile": "https://github.com/JTunis", + "contributions": [ + "ideas", + "code", + "bug" + ] + }, + { + "login": "mikematos84", + "name": "Michael Matos", + "avatar_url": "https://avatars.githubusercontent.com/u/4093433?v=4", + "profile": "https://mikematos84.github.io", + "contributions": [ + "bug" + ] + }, + { + "login": "fatmcgav-depop", + "name": "Gavin Williams", + "avatar_url": "https://avatars.githubusercontent.com/u/109519102?v=4", + "profile": "https://github.com/fatmcgav-depop", + "contributions": [ + "ideas" + ] + }, + { + "login": "msiebeneicher", + "name": "Marc Siebeneicher", + "avatar_url": "https://avatars.githubusercontent.com/u/5821183?v=4", + "profile": "https://github.com/msiebeneicher", + "contributions": [ + "ideas", + "code", + "bug", + "doc" + ] + }, + { + "login": "LuisHenri", + "name": "LuΓ­s Henrique A. SchΓΌnemann", + "avatar_url": "https://avatars.githubusercontent.com/u/44511825?v=4", + "profile": "https://github.com/LuisHenri", + "contributions": [ + "ideas", + "doc", + "code" + ] + }, + { + "login": "george-gca", + "name": "George", + "avatar_url": "https://avatars.githubusercontent.com/u/31376482?v=4", + "profile": "https://github.com/george-gca", + "contributions": [ + "question", + "doc", + "ideas" + ] + }, + { + "login": "pedrorrivero", + "name": "Pedro Rivero", + "avatar_url": "https://avatars.githubusercontent.com/u/52980156?v=4", + "profile": "http://www.linkedin.com/in/pedrorrivero/", + "contributions": [ + "ideas" + ] + }, + { + "login": "ebronson68", + "name": "Eleanor Bronson", + "avatar_url": "https://avatars.githubusercontent.com/u/111298136?v=4", + "profile": "https://github.com/ebronson68", + "contributions": [ + "ideas" + ] + }, + { + "login": "marvin-belonio", + "name": "Marvin Osswald", + "avatar_url": "https://avatars.githubusercontent.com/u/88089002?v=4", + "profile": "https://github.com/marvin-belonio", + "contributions": [ + "doc" + ] + }, + { + "login": "dotdc", + "name": "David Calvert", + "avatar_url": "https://avatars.githubusercontent.com/u/12827900?v=4", + "profile": "https://github.com/dotdc", + "contributions": [ + "doc", + "bug", + "code", + "maintenance", + "blog" + ] + }, + { + "login": "aairey", + "name": "Andy Airey", + "avatar_url": "https://avatars.githubusercontent.com/u/7644094?v=4", + "profile": "https://blog.airey.be", + "contributions": [ + "bug", + "review" + ] + }, + { + "login": "Fs02", + "name": "Surya Asriadie", + "avatar_url": "https://avatars.githubusercontent.com/u/3049307?v=4", + "profile": "https://fs02.github.io/", + "contributions": [ + "bug" + ] + }, + { + "login": "jellllly420", + "name": "jellllly420", + "avatar_url": "https://avatars.githubusercontent.com/u/64725601?v=4", + "profile": "https://github.com/jellllly420", + "contributions": [ + "ideas", + "question", + "doc" + ] + }, + { + "login": "xontab", + "name": "Shaun Tabone", + "avatar_url": "https://avatars.githubusercontent.com/u/4987684?v=4", + "profile": "http://www.xontab.com", + "contributions": [ + "code" + ] + }, + { + "login": "kevin-aude", + "name": "Kevin AUDE", + "avatar_url": "https://avatars.githubusercontent.com/u/98819045?v=4", + "profile": "https://github.com/kevin-aude", + "contributions": [ + "ideas", + "code" + ] + }, + { + "login": "jnig", + "name": "Jakob", + "avatar_url": "https://avatars.githubusercontent.com/u/3729585?v=4", + "profile": "https://github.com/Jnig", + "contributions": [ + "review" + ] + }, + { + "login": "kdeldycke", + "name": "Kevin Deldycke", + "avatar_url": "https://avatars.githubusercontent.com/u/159718?v=4", + "profile": "https://kevin.deldycke.com", + "contributions": [ + "bug", + "ideas", + "code" + ] + }, + { + "login": "JessicaS11", + "name": "Jessica Scheick", + "avatar_url": "https://avatars.githubusercontent.com/u/11756442?v=4", + "profile": "https://github.com/JessicaS11", + "contributions": [ + "bug" + ] + }, + { + "login": "gasbi", + "name": "Gaspar Melsion", + "avatar_url": "https://avatars.githubusercontent.com/u/10176387?v=4", + "profile": "https://github.com/gasbi", + "contributions": [ + "ideas" + ] + }, + { + "login": "kanno41", + "name": "Ken Harding", + "avatar_url": "https://avatars.githubusercontent.com/u/2818651?v=4", + "profile": "https://github.com/kanno41", + "contributions": [ + "code", + "bug" + ] + }, + { + "login": "JakobHavtorn", + "name": "Jakob Drachmann Havtorn", + "avatar_url": "https://avatars.githubusercontent.com/u/10236734?v=4", + "profile": "https://jakobhavtorn.github.io/", + "contributions": [ + "ideas" + ] + }, + { + "login": "brian6932", + "name": "Brian", + "avatar_url": "https://avatars.githubusercontent.com/u/18603393?v=4", + "profile": "https://github.com/brian6932", + "contributions": [ + "doc" + ] + }, + { + "login": "MuriloChianfa", + "name": "MuriloChianfa", + "avatar_url": "https://avatars.githubusercontent.com/u/60560085?v=4", + "profile": "https://github.com/MuriloChianfa", + "contributions": [ + "doc" + ] + }, + { + "login": "davidsnyder", + "name": "David Snyder", + "avatar_url": "https://avatars.githubusercontent.com/u/229108?v=4", + "profile": "https://github.com/davidsnyder", + "contributions": [ + "research" + ] + }, + { + "login": "TechnicallyJoe", + "name": "Jonathan Østrup", + "avatar_url": "https://avatars.githubusercontent.com/u/7877957?v=4", + "profile": "https://github.com/technicallyjoe", + "contributions": [ + "ideas", + "code" + ] + }, + { + "login": "icco", + "name": "Nat Welch", + "avatar_url": "https://avatars.githubusercontent.com/u/20201?v=4", + "profile": "https://natwelch.com", + "contributions": [ + "bug", + "code" + ] + }, + { + "login": "PepijnB", + "name": "Pepijn Boer", + "avatar_url": "https://avatars.githubusercontent.com/u/24453103?v=4", + "profile": "https://github.com/PepijnB", + "contributions": [ + "bug", + "doc" + ] + }, + { + "login": "alexvanderberkel", + "name": "Alex", + "avatar_url": "https://avatars.githubusercontent.com/u/862899?v=4", + "profile": "https://github.com/alexvanderberkel", + "contributions": [ + "code", + "ideas", + "review", + "test" + ] + }, + { + "login": "yuhengshen", + "name": "yuhengshen", + "avatar_url": "https://avatars.githubusercontent.com/u/29867660?v=4", + "profile": "https://github.com/yuhengshen", + "contributions": [ + "bug", + "code" + ] + } + ], + "contributorsPerLine": 7, + "projectName": "actions-template-sync", + "projectOwner": "AndreasAugustin", + "repoType": "github", + "repoHost": "https://github.com", + "skipCi": true, + "commitConvention": "angular", + "commitType": "docs" +} diff --git a/third_party/AndreasAugustin/actions-template-sync/.devcontainer/devcontainer.json b/third_party/AndreasAugustin/actions-template-sync/.devcontainer/devcontainer.json new file mode 100644 index 00000000..f27e7179 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.devcontainer/devcontainer.json @@ -0,0 +1,34 @@ +// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.112.0/containers/docker-existing-docker-compose +// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml. +{ + "name": "Existing Docker Compose (Extend)", + // Update the 'dockerComposeFile' list if you have more compose files or use different names. + // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make. + "dockerComposeFile": [ + "../docker-compose.yml", + "docker-compose.yml" + ], + // The 'service' property is the name of the service for the container that VS Code should + // use. Update this value and .devcontainer/docker-compose.yml to the real service name. + "service": "dev", + // The optional 'workspaceFolder' property is the path VS Code should open by default when + // connected. This is typically a file mount in .devcontainer/docker-compose.yml + "workspaceFolder": "/workspace", + // Set *default* container specific settings.json values on container create. + "settings": { + "terminal.integrated.shell.linux": "/bin/zsh" + }, + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "DavidAnson.vscode-markdownlint" + ] + // Uncomment the next line if you want start specific services in your Docker Compose config. + // "runServices": [], + // Uncomment the next line if you want to keep your containers running after VS Code shuts down. + // "shutdownAction": "none", + // Uncomment the next line to run commands after the container is created - for example installing git. + // "postCreateCommand": "apt-get update && apt-get install -y git", + // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. + // "remoteUser": "vscode" +} \ No newline at end of file diff --git a/third_party/AndreasAugustin/actions-template-sync/.devcontainer/docker-compose.yml b/third_party/AndreasAugustin/actions-template-sync/.devcontainer/docker-compose.yml new file mode 100644 index 00000000..aa8d45ea --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.devcontainer/docker-compose.yml @@ -0,0 +1,41 @@ +--- +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- + +services: + # Update this to the name of the service you want to work with in your docker-compose.yml file + dev: + # You may want to add a non-root user to your Dockerfile and uncomment the line below + # to cause all processes to run as this user. Once present, you can also simply + # use the "remoteUser" property in devcontainer.json if you just want VS Code and + # its sub-processes (terminals, tasks, debugging) to execute as the user. On Linux, + # you may need to ensure the UID and GID of the container user you create matches your + # local user. See https://aka.ms/vscode-remote/containers/non-root for details. + # user: vscode + + # Uncomment if you want to add a different Dockerfile in the .devcontainer folder + # build: + # context: . + # dockerfile: Dockerfile + + # Uncomment if you want to expose any additional ports. The snippet below exposes port 3000. + # ports: + # - 3000:3000 + + volumes: + # Update this to wherever you want VS Code to mount the folder of your project + - .:/workspace:cached + + # Uncomment the next line to use Docker from inside the container. See https://aka.ms/vscode-remote/samples/docker-in-docker-compose for details. + # - /var/run/docker.sock:/var/run/docker.sock + + # Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust. + # cap_add: + # - SYS_PTRACE + # security_opt: + # - seccomp:unconfined + + # Overrides default command so things don't shut down after the process ends. + command: /bin/sh -c "while sleep 1000; do :; done" diff --git a/third_party/AndreasAugustin/actions-template-sync/.dockerignore b/third_party/AndreasAugustin/actions-template-sync/.dockerignore new file mode 100644 index 00000000..3a42fca5 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.dockerignore @@ -0,0 +1,3 @@ +.github/ +.devcontainer/ +.dependabot/ diff --git a/third_party/AndreasAugustin/actions-template-sync/.editorconfig b/third_party/AndreasAugustin/actions-template-sync/.editorconfig new file mode 100644 index 00000000..0e4fbfb7 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.editorconfig @@ -0,0 +1,29 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true + +[*.md] +indent_style = space +indent_size = 2 +max_line_length = 80 + +[*.{json,yml}] +indent_style = space +indent_size = 2 + +# Tab indentation (no size specified) +[Makefile] +indent_style = tab +indent_size = 4 + +[*.sh] +indent_size = 2 +indent_style = space diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/CODEOWNERS b/third_party/AndreasAugustin/actions-template-sync/.github/CODEOWNERS new file mode 100644 index 00000000..4e341619 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +* @AndreasAugustin diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/CODE_OF_CONDUCT.md b/third_party/AndreasAugustin/actions-template-sync/.github/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..76975418 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,77 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at dev@andreas-augustin.org. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html][conduct] + +[homepage]: https://www.contributor-covenant.org +[conduct]: https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +For answers to common questions about this code of conduct, see +[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/CONTRIBUTING.md b/third_party/AndreasAugustin/actions-template-sync/.github/CONTRIBUTING.md new file mode 100644 index 00000000..f662cc29 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/CONTRIBUTING.md @@ -0,0 +1,58 @@ +# Contributing + +## Branching model + +We use the [GitHub flow](https://guides.github.com/introduction/flow/) + +## Commit messages + +We use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) +Please als add an issue and the issue number as prefix to your commit message header description. + +```bash +git commit -m "[optional scope]: (#ticket_nr) " +``` + +### Emojis + +Feel free to add emojis to your message. + +| Emoji | Raw Emoji Code | Type | Description | +|:--------------------------:|------------------------------|--------------------|-------------| +| :star: | `:star:` | `new` or `feature` | add **new feature** | +| :bug: | `:bug:` | `bug` | fix **bug** issue | +| :ambulance: | `:ambulance:` | `bug` | ciritial hotfix **bug** issue | +| :lock: | `:lock:` | `security` | fix **security** issue | +| :chart_with_upwards_trend: | `:chart_with_upwards_trend:` | `performance` | fix **performance** issue | +| :zap: | `:zap:` | `improvement` | update **backwards-compatible** feature | +| :boom: | `:boom` | `breaking` | update **backwards-incompatible** feature | +| :warning: | `:warning:` | `deprecated` | **deprecate** feature | +| :globe_with_meridians: | `:globe_with_meridians:` | `i18n` | update or fix **internationalization** | +| :wheelchair: | `:wheelchair:` | `a11y` | update or fix **accessibility** | +| :lipstick: | `:lipstick:` | `update` | update **UI/Cosmetic** | +| :up: | `:up:` | `update` | update **other** | +| :rotating_light: | `:rotating_light:` | `refactor` | remove **linter**/strict/deprecation warnings | +| :shirt: | `:shirt:` | `refactor` | **refactoring** or code **layouting** | +| :white_check_mark: | `:white_check_mark:` | `test` | add **tests** | +| :green_heart: | `:green_heart:` | `test` | fix **tests** failur or **CI** building | +| :pencil: | `:pencil:` | `docs` | update **documentation** | +| :copyright: | `:copyright:` | `docs` | decide or change **license** | +| :lollipop: | `:lollipop:` | `example` | for **example** or **demo** codes | +| :arrow_up: | `:arrow_up:` | `dependency` | upgrade **dependencies** | +| :arrow_down: | `:arrow_down:` | `dependency` | downgrade **dependencies** | +| :pushpin: | `:pushpin:` | `dependency` | pin **dependencies** | +| :wrench: | `:wrench:` | `config` | update **configuration** | +| :package: | `:package:` | `build` | **packaging** or **bundling** or **building** | +| :hatching_chick: | `:hatching_chick:` | `release` | **initial** commit | +| :confetti_ball: | `:confetti_ball:` | `release` | release **major** version | +| :tada: | `:tada:` | `release` | release **minor** version | +| :sparkles: | `:sparkles:` | `release` | release **patch** version | +| :rocket: | `:rocket:` | `release` | **deploy** to production enviroment | +| :bookmark: | `:bookmark:` | `release` | **tagged** with version label | +| :back: | `:back:` | `revert` | **revert** commiting | +| :construction: | `:construction:` | `wip` | **WIP** commiting | +| :truck: | `:truck:` | `move` | **move** or **rename** files, repository, ... | +| :twisted_rightwards_arrows:| `:twisted_rightwards_arrows:`| - | merge **conflict resolution** | +| :heavy_plus_sign: | `:heavy_plus_sign:` | - | **add** files, dependencies, ... | +| :heavy_minus_sign: | `:heavy_minus_sign:` | - | **remove** files, dependencies, ... | +| :on: | `:on:` | - | **enable** feature and something ... | diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/FUNDING.yml b/third_party/AndreasAugustin/actions-template-sync/.github/FUNDING.yml new file mode 100644 index 00000000..864e3c56 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: [AndreasAugustin] +ko_fi: andreasaugustin diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/third_party/AndreasAugustin/actions-template-sync/.github/ISSUE_TEMPLATE/BUG_REPORT.yml new file mode 100644 index 00000000..372ca9f5 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -0,0 +1,81 @@ +--- +name: "πŸ› Bug Report" +description: File a bug report +title: "[Bug]: " +labels: ["bug"] +assignees: [] +body: + - type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true + - type: textarea + id: description + attributes: + label: Describe the bug + description: What is the problem? A clear and concise description of the bug. + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: | + What did you expect to happen? + validations: + required: true + - type: textarea + id: current + attributes: + label: Current Behavior + description: Describe the behavior + placeholder: |- + In the X repository in Y service I'm encountering Z error. See trace: + + ``` + Please include full errors, uncaught exceptions, stack traces, and + relevant logs. + + If possible enable DEBUG logging by creating a secret named `ACTIONS_STEP_DEBUG` with the value `true` + ``` + validations: + required: true + - type: textarea + attributes: + label: Steps To Reproduce + description: Steps to reproduce the behavior. + placeholder: | + 1. In this environment... + 2. With this config... + 3. Run '...' + 4. See error... + validations: + required: false + - type: textarea + id: solution + attributes: + label: Possible Solution + description: | + Suggest a fix/reason for the bug + validations: + required: false + - type: textarea + id: context + attributes: + label: Additional Information/Context + description: | + Anything else that might be relevant for troubleshooting this bug. + Providing context helps us come up with a solution that is most useful + in the real world. + validations: + required: false + - type: input + id: actions-template-sync-version + attributes: + label: Template sync version Version + description: The template sync version you are running. + validations: + required: true diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/ISSUE_TEMPLATE/DOC_TEMPLATE.yml b/third_party/AndreasAugustin/actions-template-sync/.github/ISSUE_TEMPLATE/DOC_TEMPLATE.yml new file mode 100644 index 00000000..b1d39083 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/ISSUE_TEMPLATE/DOC_TEMPLATE.yml @@ -0,0 +1,29 @@ +--- +name: "πŸ“• Documentation Issue" +description: Report an issue in the documentation +title: "[Docs]: " +labels: [docs] +assignees: [] +body: + - type: textarea + id: description + attributes: + label: Describe the documentation issue + description: A clear and concise description of the documentation issue. + validations: + required: true + - type: textarea + id: links + attributes: + label: Links + description: | + Include links to affected documentation page(s). + validations: + required: true + - type: checkboxes + id: ack + attributes: + label: Acknowledgements + options: + - label: I may be able to submit a pull-request to fix this issue. + required: false diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml b/third_party/AndreasAugustin/actions-template-sync/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml new file mode 100644 index 00000000..9d4e600d --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml @@ -0,0 +1,40 @@ +--- +name: πŸš€ Feature Request +description: Suggest an idea for this project +title: "[Feat]: " +labels: [feature] +assignees: [] +body: + - type: textarea + id: description + attributes: + label: Describe the feature + description: | + A clear and concise description of the feature you are proposing. + validations: + required: true + - type: textarea + id: use-case + attributes: + label: Use Case + description: | + Why do you need this feature? For example: "I'm always frustrated + when...", "I have a customer that needs..." + validations: + required: true + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: | + Suggest how to implement the addition or change. Please include + prototype/workaround/sketch/reference implementation. + validations: + required: false + - type: checkboxes + id: ack + attributes: + label: Acknowledgements + options: + - label: I may be able to implement this feature request + required: false diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/PULL_REQUEST_TEMPLATE.md b/third_party/AndreasAugustin/actions-template-sync/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..1d9e498a --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,10 @@ +# Description + +Close # + + + +## Remark + +For automation please see [closing-issues-using-keywords]( + https://help.github.com/en/articles/closing-issues-using-keywords) diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/SECURITY.md b/third_party/AndreasAugustin/actions-template-sync/.github/SECURITY.md new file mode 100644 index 00000000..585a96b3 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/SECURITY.md @@ -0,0 +1,8 @@ +# Security Policy + +## Reporting a Vulnerability + +If you find a [security vulnerability advisory](https://github.com/AndreasAugustin/actions-template-sync/security/advisories/new) + +- click issues +- click report a vulnerability diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/dependabot.yml b/third_party/AndreasAugustin/actions-template-sync/.github/dependabot.yml new file mode 100644 index 00000000..61114fa9 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" +- package-ecosystem: docker + directory: "/" + schedule: + interval: weekly + time: "04:00" + open-pull-requests-limit: 10 diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/labeler.yml b/third_party/AndreasAugustin/actions-template-sync/.github/labeler.yml new file mode 100644 index 00000000..ca008019 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/labeler.yml @@ -0,0 +1,10 @@ +# this file is for the labeler workflow job +# Documentation https://github.com/marketplace/actions/labeler +documentation: + - docs/**/* + - .github/* + - ./*.md + +ci: + - .dependabot/* + - .github/workflows/* diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/actions_template_sync.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/actions_template_sync.yml new file mode 100644 index 00000000..460248ef --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/actions_template_sync.yml @@ -0,0 +1,27 @@ +name: actions-template-sync + +on: + # cronjob trigger At 00:00 on day-of-month 1. https://crontab.guru/every-month + schedule: + - cron: "0 0 1 * *" + # manual trigger + workflow_dispatch: + +jobs: + repo-sync: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + - name: actions-template-sync + uses: AndreasAugustin/actions-template-sync@v2 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + source_repo_path: AndreasAugustin/template + upstream_branch: main # defaults to main + pr_labels: chore,πŸ“š template-sync,example diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/gh_pages_mk_docs.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/gh_pages_mk_docs.yml new file mode 100644 index 00000000..d55e9fc6 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/gh_pages_mk_docs.yml @@ -0,0 +1,19 @@ +name: gh-pages-mk-docs +on: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.x + - run: pip install mkdocs-material + - run: mkdocs gh-deploy --force diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/lint.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/lint.yml new file mode 100644 index 00000000..7b0e9a43 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/lint.yml @@ -0,0 +1,20 @@ +name: Lint + +on: + push: + branches: + - "!main" + pull_request: + workflow_call: + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: markdownlint + run: make markdownlint + - name: prune + run: make prune diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/push_docker.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/push_docker.yml new file mode 100644 index 00000000..4d79a27e --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/push_docker.yml @@ -0,0 +1,99 @@ +name: push-docker + +on: + workflow_call: + inputs: + tag: + description: "The docker image tag" + required: true + type: string + secrets: + DOCKERHUB_USERNAME: + description: "The dockerhub username" + required: true + DOCKERHUB_TOKEN: + description: "The dockerhub token" + required: true + workflow_dispatch: + inputs: + tag: + description: "The docker image tag" + required: true + type: string + +jobs: + build_and_push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + strategy: + matrix: + variant: ["actions-template-sync"] + target: ["prod", "dev"] + + steps: + - name: checkout + uses: actions/checkout@v4 + - name: Login to DockerHub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to GHCR + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: | + andyaugustin/${{ matrix.variant }} + ghcr.io/andreasaugustin/${{ matrix.variant }} + tags: | + type=semver,pattern={{raw}},value=${{ inputs.tag }}${{ matrix.target == 'dev' && '-dev' || '' }} + - name: Build ${{ matrix.variant }} + uses: docker/build-push-action@v6 + with: + context: . + target: ${{ matrix.target }} + load: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + - name: install container test tools + run: | + echo "Install container tools" + curl -LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-amd64 \ + && chmod +x container-structure-test-linux-amd64 \ + && sudo mv container-structure-test-linux-amd64 /usr/local/bin/container-structure-test + - name: test docker image + run: | + echo "Run tests" + container-structure-test test \ + --image andyaugustin/${{ matrix.variant }}:${{ inputs.tag }}${{ matrix.target == 'dev' && '-dev' || '' }}\ + --config docker-test-config.yml + container-structure-test test \ + --image ghcr.io/andreasaugustin/${{ matrix.variant }}:${{ inputs.tag }}${{ matrix.target == 'dev' && '-dev' || '' }}\ + --config docker-test-config.yml + - name: push ${{ matrix.variant }} + uses: docker/build-push-action@v6 + with: + context: . + target: ${{ matrix.target }} + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + - name: Docker Hub Description + uses: peter-evans/dockerhub-description@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + repository: andyAugustin/${{ matrix.variant }} + readme-filepath: ./docs/DOCKER.md + short-description: See https://github.com/${{ github.repository }} to have a look into the source code. diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/release.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/release.yml new file mode 100644 index 00000000..3a2dfcf8 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/release.yml @@ -0,0 +1,49 @@ +name: release + +on: + push: + branches: + - main + +jobs: + call_shellcheck: + uses: ./.github/workflows/shellcheck.yml + call_lint: + uses: ./.github/workflows/lint.yml + call_test_all: + uses: ./.github/workflows/test_all.yml + secrets: inherit + permissions: + contents: write + pull-requests: write + call_release_please: + needs: + - call_shellcheck + - call_lint + - call_test_all + permissions: + contents: write + pull-requests: write + uses: ./.github/workflows/release_please.yml + call_push_docker: + if: ${{ needs.call_release_please.outputs.release_created }} + needs: + - call_release_please + permissions: + contents: read + packages: write + uses: ./.github/workflows/push_docker.yml + with: + tag: ${{ needs.call_release_please.outputs.tag_name }} + secrets: inherit + call_release_test_docker_images: + if: ${{ needs.call_release_please.outputs.release_created }} + needs: + - call_push_docker + - call_release_please + permissions: + packages: read + uses: ./.github/workflows/release_test_docker_images.yml + with: + tag: ${{ needs.call_release_please.outputs.tag_name }} + secrets: inherit diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/release_please.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/release_please.yml new file mode 100644 index 00000000..64869d9a --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/release_please.yml @@ -0,0 +1,44 @@ +name: release-please + +on: + workflow_call: + outputs: + release_created: + description: "Set if the release has been created" + value: ${{ jobs.release_please.outputs.release_created }} + tag_name: + description: "The tag name" + value: ${{ jobs.release_please.outputs.tag_name }} + + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + release_please: + runs-on: ubuntu-latest + outputs: + release_created: ${{ steps.release.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + steps: + - uses: googleapis/release-please-action@v4 + id: release + with: + release-type: simple + - uses: actions/checkout@v4 + - name: tag major and minor versions + if: ${{ steps.release.outputs.release_created }} + run: | + git config user.name github-actions[bot] + git config user.email 41898282+github-actions[bot]@users.noreply.github.com + git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/google-github-actions/release-please-action.git" + git tag -d v${{ steps.release.outputs.major }} || true + git tag -d v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }} || true + git push origin :v${{ steps.release.outputs.major }} || true + git push origin :v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }} || true + git tag -a v${{ steps.release.outputs.major }} -m "Release v${{ steps.release.outputs.major }}" + git tag -a v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }} -m "Release v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}" + git push origin v${{ steps.release.outputs.major }} + git push origin v${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }} diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/release_test_docker_images.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/release_test_docker_images.yml new file mode 100644 index 00000000..78a1bfa3 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/release_test_docker_images.yml @@ -0,0 +1,63 @@ +name: release-test-docker-images + +on: + workflow_call: + inputs: + tag: + description: "The docker image tag" + required: true + type: string + secrets: + DOCKERHUB_USERNAME: + description: "The dockerhub username" + required: true + DOCKERHUB_TOKEN: + description: "The dockerhub token" + required: true + workflow_dispatch: + inputs: + tag: + description: "The docker image tag" + required: true + type: string + +permissions: + packages: read + +jobs: + test-docker-images: + strategy: + matrix: + docker-image: + - ghcr.io/andreasaugustin/actions-template-sync + - andyaugustin/actions-template-sync + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + lfs: true + fetch-depth: 0 + - name: Login to DockerHub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: pull image + run: | + docker pull ${{ matrix.docker-image }}:${{ inputs.tag }} + - name: run tests + run: | + echo "Install container tools" + curl -LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-amd64 \ + && chmod +x container-structure-test-linux-amd64 \ + && sudo mv container-structure-test-linux-amd64 /usr/local/bin/container-structure-test + echo "Run tests" + container-structure-test test \ + --image ${{ matrix.docker-image }}:${{ inputs.tag }} \ + --config docker-test-config.yml diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/shellcheck.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/shellcheck.yml new file mode 100644 index 00000000..ed48cb72 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/shellcheck.yml @@ -0,0 +1,18 @@ +name: shellcheck + +on: + push: + branches: + - "!main" + pull_request: + workflow_call: + workflow_dispatch: + +jobs: + shellcheck: + name: Shellcheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run shellcheck in container + run: make shellcheck diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test.yml new file mode 100644 index 00000000..194c6110 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test.yml @@ -0,0 +1,52 @@ +name: test + +on: + push: + # branches: + # - "!main" + # pull_request: + workflow_call: + workflow_dispatch: + +jobs: + test-implementation-job: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + - name: Test action step + id: test + uses: ./ # Uses an action in the root directory + with: + source_repo_path: AndreasAugustin/template.git + is_dry_run: true + is_force_push_pr: true + - name: print output + env: + FORMER_OUTPUT_PR_BRANCH: ${{ steps.test.outputs.pr_branch }} + run: echo "pr_branch ${FORMER_OUTPUT_PR_BRANCH}" + + test-implementation-job-no-dry-run: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + - name: Test action step + id: test + uses: ./ # Uses an action in the root directory + with: + source_repo_path: AndreasAugustin/template.git + is_dry_run: false + is_force_push_pr: true + - name: print output + env: + FORMER_OUTPUT_PR_BRANCH: ${{ steps.test.outputs.pr_branch }} + run: echo "pr_branch ${FORMER_OUTPUT_PR_BRANCH}" diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_all.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_all.yml new file mode 100644 index 00000000..6ae73535 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_all.yml @@ -0,0 +1,53 @@ +name: test-all + +on: + push: + branches: + - "!main" + # pull_request: + workflow_call: + workflow_dispatch: + +jobs: + call_test_hooks: + uses: ./.github/workflows/test_hooks.yml + secrets: inherit + permissions: + contents: write + pull-requests: write + # call_github_app_test_target_org: + # uses: ./.github/workflows/test_github_app_target_org.yml + # secrets: inherit + # permissions: + # contents: write + # pull-requests: write + # call_github_app_test: + # uses: ./.github/workflows/test_github_app.yml + # secrets: inherit + # permissions: + # contents: write + # pull-requests: write + call_test_ssh_gitlab: + uses: ./.github/workflows/test_ssh_gitlab.yml + secrets: inherit + permissions: + contents: write + pull-requests: write + call_test_ssh: + uses: ./.github/workflows/test_ssh.yml + secrets: inherit + permissions: + contents: write + pull-requests: write + call_test: + uses: ./.github/workflows/test.yml + secrets: inherit + permissions: + contents: write + pull-requests: write + call_test_steps: + uses: ./.github/workflows/test_steps.yml + secrets: inherit + permissions: + contents: write + pull-requests: write diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_github_app.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_github_app.yml new file mode 100644 index 00000000..c3e25692 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_github_app.yml @@ -0,0 +1,48 @@ +name: test-github_app + +on: + push: + # branches: + # - "!main" + # pull_request: + workflow_call: + workflow_dispatch: + +jobs: + test-implementation-job: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + # To use this repository's private action, you must check out the repository + - name: token-generation + uses: actions/create-github-app-token@v2 + id: source-app-token + with: + app-id: ${{ secrets.TEST_GITHUB_APP_ID }} + private-key: ${{ secrets.TEST_APP_PEM_FILE }} + owner: alexvanderberkel + repositories: private-test-repo + + - name: Checkout + # https://github.com/actions/checkout#usage + uses: actions/checkout@v4 + with: + token: ${{ steps.source-app-token.outputs.token }} + persist-credentials: false # Don't set this to true as otherwise the token will be stored in the local git config and the run will fail + + - name: Test action step + uses: ./ # Uses an action in the root directory + env: + MY_VAR: "bar" + with: + source_repo_path: alexvanderberkel/private-test-repo + source_gh_token: ${{ steps.source-app-token.outputs.token }} + # target_gh_token: ${{ github.token }} + upstream_branch: main + is_dry_run: false + is_allow_hooks: true + + + diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_hooks.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_hooks.yml new file mode 100644 index 00000000..f1b13033 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_hooks.yml @@ -0,0 +1,29 @@ +name: test-hooks + +on: + push: + # branches: + # - "!main" + # pull_request: + workflow_call: + workflow_dispatch: + +jobs: + test-implementation-job: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + - name: Test action step + uses: ./ # Uses an action in the root directory + env: + MY_VAR: "bar" + with: + source_repo_path: AndreasAugustin/template.git + upstream_branch: main + is_dry_run: true + is_allow_hooks: true diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_ssh.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_ssh.yml new file mode 100644 index 00000000..09406f17 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_ssh.yml @@ -0,0 +1,27 @@ +name: test-ssh + +on: + push: + # branches: + # - "!main" + # pull_request: + workflow_call: + workflow_dispatch: + +jobs: + test-implementation-job: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + - name: Test action step ssh + if: github.repository_owner == 'AndreasAugustin' + uses: ./ # Uses an action in the root directory + with: + source_repo_path: ${{ secrets.SOURCE_REPO_PATH_TEST }} # , should be within secrets + source_repo_ssh_private_key: ${{ secrets.SOURCE_REPO_SSH_PRIVATE_KEY }} # contains the private ssh key of the private repository + is_dry_run: true diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_ssh_gitlab.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_ssh_gitlab.yml new file mode 100644 index 00000000..a78ef422 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_ssh_gitlab.yml @@ -0,0 +1,29 @@ +name: test-ssh-gitlab + +on: + push: + # branches: + # - "!main" + # pull_request: + workflow_call: + workflow_dispatch: + +jobs: + test-implementation-job: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + - name: Test action step ssh + if: github.repository_owner == 'AndreasAugustin' + uses: ./ # Uses an action in the root directory + with: + hostname: ${{ secrets.SOURCE_REPO_GITLAB_HOSTNAME }} + source_repo_path: ${{ secrets.SOURCE_REPO_GITLAB_PATH }} # , should be within secrets + source_repo_ssh_private_key: ${{ secrets.SOURCE_REPO_GITLAB_SSH_PRIVATE_KEY }} # contains the private ssh key of the private repository + is_dry_run: true + is_not_source_github: true diff --git a/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_steps.yml b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_steps.yml new file mode 100644 index 00000000..8a219ed3 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.github/workflows/test_steps.yml @@ -0,0 +1,47 @@ +name: test-steps + +on: + push: + # branches: + # - "!main" + # pull_request: + workflow_call: + workflow_dispatch: + +jobs: + test-implementation-job: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + + - name: Test action step first steps + uses: ./ # Uses an action in the root directory + with: + source_repo_path: AndreasAugustin/template.git + is_dry_run: true + is_force_push_pr: true + steps: "prechecks,pull" + + - name: in between step + run: | + echo "I can do whatever I want" + git status + + - name: Test action step next steps + uses: ./ # Uses an action in the root directory + id: test + with: + source_repo_path: AndreasAugustin/template.git + is_dry_run: true + is_force_push_pr: true + steps: "commit,push,pr" + + - name: print output + env: + FORMER_OUTPUT_PR_BRANCH: ${{ steps.test.outputs.pr_branch }} + run: echo "pr_branch ${FORMER_OUTPUT_PR_BRANCH}" diff --git a/third_party/AndreasAugustin/actions-template-sync/.gitignore b/third_party/AndreasAugustin/actions-template-sync/.gitignore new file mode 100644 index 00000000..c38c8c29 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.gitignore @@ -0,0 +1,6 @@ +.env +tmp* +TODO.md + +.venv/ + diff --git a/third_party/AndreasAugustin/actions-template-sync/.markdownlintignore b/third_party/AndreasAugustin/actions-template-sync/.markdownlintignore new file mode 100644 index 00000000..2468c074 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.markdownlintignore @@ -0,0 +1,2 @@ +node_modules/ +CHANGELOG.md diff --git a/third_party/AndreasAugustin/actions-template-sync/.markdownlintrc b/third_party/AndreasAugustin/actions-template-sync/.markdownlintrc new file mode 100644 index 00000000..876c16c4 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.markdownlintrc @@ -0,0 +1,4 @@ +{ + "default": true, + "MD013": { "line_length": 150, "tables": false } +} diff --git a/third_party/AndreasAugustin/actions-template-sync/.templatesyncignore b/third_party/AndreasAugustin/actions-template-sync/.templatesyncignore new file mode 100644 index 00000000..005f3ecc --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/.templatesyncignore @@ -0,0 +1,8 @@ +.all-contributorsrc +.github/dependabot.yml +README.md +Dockerfile +SECURITY.md +docker-compose.yml +Makefile +.github/workflows/* diff --git a/third_party/AndreasAugustin/actions-template-sync/CHANGELOG.md b/third_party/AndreasAugustin/actions-template-sync/CHANGELOG.md new file mode 100644 index 00000000..ec918891 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/CHANGELOG.md @@ -0,0 +1,267 @@ +# Changelog + +## [2.5.2](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.5.1...v2.5.2) (2025-07-16) + + +### Bug Fixes + +* **docs:** new markdownlint issue ([47e25cf](https://github.com/AndreasAugustin/actions-template-sync/commit/47e25cfd55b45f0ba5ef2f7bef611dfac766cdeb)) + +## [2.5.1](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.5.0...v2.5.1) (2025-02-17) + + +### Bug Fixes + +* **#608:** workaround ([#614](https://github.com/AndreasAugustin/actions-template-sync/issues/614)) ([fffd6ca](https://github.com/AndreasAugustin/actions-template-sync/commit/fffd6caf36570bf6f2099defe545cc8d4b9c625e)) + +## [2.5.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.4.2...v2.5.0) (2025-01-31) + + +### Features + +* **#598:** enable possibility to have source repository in other organisation ([3247499](https://github.com/AndreasAugustin/actions-template-sync/commit/32474992795a695d4a42779a591f418e9175e665)) + +## [2.4.2](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.4.1...v2.4.2) (2025-01-07) + + +### Bug Fixes + +* **#551:** fix issue with file deletion ([#596](https://github.com/AndreasAugustin/actions-template-sync/issues/596)) ([1641155](https://github.com/AndreasAugustin/actions-template-sync/commit/164115568a2f8a4ea67dda06f786a9c90624971d)) +* **#591:** add missing gh cli precheck ([#594](https://github.com/AndreasAugustin/actions-template-sync/issues/594)) ([574812a](https://github.com/AndreasAugustin/actions-template-sync/commit/574812a4ea91dcaa3ffe39ace616fd329b209e43)) + +## [2.4.1](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.4.0...v2.4.1) (2024-10-15) + + +### Bug Fixes + +* incorrect argument passing to git push ([#574](https://github.com/AndreasAugustin/actions-template-sync/issues/574)) ([44e59ba](https://github.com/AndreasAugustin/actions-template-sync/commit/44e59ba38bf03b73ddf96462365826b01cf7f1b8)) + +## [2.4.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.3.0...v2.4.0) (2024-10-15) + + +### Features + +* **#567:** Add the name of the .templatesyncignore file as a parameter ([#568](https://github.com/AndreasAugustin/actions-template-sync/issues/568)) ([03661a8](https://github.com/AndreasAugustin/actions-template-sync/commit/03661a8560de11c0fb0203642f69799f481286bd)) + +## [2.3.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.2.3...v2.3.0) (2024-10-14) + + +### Features + +* **#547:** :sparkles: add option to include git tags ([#561](https://github.com/AndreasAugustin/actions-template-sync/issues/561)) ([01f7623](https://github.com/AndreasAugustin/actions-template-sync/commit/01f7623dbfc8f73ccaf1635d64cb629a699acc9a)) + +## [2.2.3](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.2.2...v2.2.3) (2024-06-19) + + +### Bug Fixes + +* **#536:** :bug: issue with comments within .templatesyncignore ([#538](https://github.com/AndreasAugustin/actions-template-sync/issues/538)) ([aba0971](https://github.com/AndreasAugustin/actions-template-sync/commit/aba0971640d113cd858cfbb6b9eb2f4c2de09049)) + +## [2.2.2](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.2.1...v2.2.2) (2024-06-16) + + +### Bug Fixes + +* **#529:** :bug: edge case with branch cleanup and force push ([#534](https://github.com/AndreasAugustin/actions-template-sync/issues/534)) ([ab9498f](https://github.com/AndreasAugustin/actions-template-sync/commit/ab9498f63d0cf03e677228c6a2f6828adf8b4662)) + +## [2.2.1](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.2.0...v2.2.1) (2024-06-06) + + +### Bug Fixes + +* **#528:** :memo: small docs update ([4eb71ce](https://github.com/AndreasAugustin/actions-template-sync/commit/4eb71ce2acda4476ed387a8b42cd94846ca8474e)) + +## [2.2.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.1.0...v2.2.0) (2024-05-27) + + +### Features + +* **#523:** :sparkles: delete branches on pr cleanup ([#525](https://github.com/AndreasAugustin/actions-template-sync/issues/525)) ([d957348](https://github.com/AndreasAugustin/actions-template-sync/commit/d9573484779def3582a6d442502aaa69eaf674e9)) + +## [2.1.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.0.2...v2.1.0) (2024-04-23) + + +### Features + +* **#478:** :sparkles: possible to execute single steps ([#516](https://github.com/AndreasAugustin/actions-template-sync/issues/516)) ([6b9bd88](https://github.com/AndreasAugustin/actions-template-sync/commit/6b9bd8844d2a75ecf2f4d2688b7f847fd86cffa3)) + +## [2.0.2](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.0.1...v2.0.2) (2024-03-28) + + +### Bug Fixes + +* **#510:** :bug: issue with blank lines within .templatesyncignore ([#512](https://github.com/AndreasAugustin/actions-template-sync/issues/512)) ([814f456](https://github.com/AndreasAugustin/actions-template-sync/commit/814f4564aa1ce6d354dcf48a34ea5b7a670327a5)) + +## [2.0.1](https://github.com/AndreasAugustin/actions-template-sync/compare/v2.0.0...v2.0.1) (2024-03-18) + + +### Bug Fixes + +* **#507:** :bug: pr title and body internal variable substitution ([#508](https://github.com/AndreasAugustin/actions-template-sync/issues/508)) ([912b4e0](https://github.com/AndreasAugustin/actions-template-sync/commit/912b4e01a39729b00a1f928303f864294d6cbede)) + +## [2.0.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.12.0...v2.0.0) (2024-03-13) + + +### ⚠ BREAKING CHANGES + +* :sparkles: migrate from docker action to composite action ([#498](https://github.com/AndreasAugustin/actions-template-sync/issues/498)) + +### Features + +* :sparkles: migrate from docker action to composite action ([#498](https://github.com/AndreasAugustin/actions-template-sync/issues/498)) ([29d0434](https://github.com/AndreasAugustin/actions-template-sync/commit/29d04342d0bd6047538dd7f52a7e64a8ca2d4baa)) + +## [1.12.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.11.0...v1.12.0) (2024-03-13) + + +### Features + +* **#482:** :sparkles: add option to force push and pr ([#499](https://github.com/AndreasAugustin/actions-template-sync/issues/499)) ([cbef7ee](https://github.com/AndreasAugustin/actions-template-sync/commit/cbef7ee63378db46e59d89a09c055376dccf4817)) + +## [1.11.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.10.0...v1.11.0) (2024-03-11) + + +### Features + +* :sparkles: gpg sign with passphrase ([#460](https://github.com/AndreasAugustin/actions-template-sync/issues/460)) ([cec582e](https://github.com/AndreasAugustin/actions-template-sync/commit/cec582ee2fc98db86d2cb5335a33a2fdaa59f418)) + +## [1.10.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.9.0...v1.10.0) (2024-03-05) + + +### Features + +* **#467:** :sparkles: hooks now within action inputs ([#489](https://github.com/AndreasAugustin/actions-template-sync/issues/489)) ([0e55c08](https://github.com/AndreasAugustin/actions-template-sync/commit/0e55c08f95f9a83c60f809fa6b49785187ec7623)) + +## [1.9.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.8.1...v1.9.0) (2024-03-05) + + +### Features + +* :sparkles: Set token to the default provided by GitHub workflow ([#483](https://github.com/AndreasAugustin/actions-template-sync/issues/483)) ([c1e7561](https://github.com/AndreasAugustin/actions-template-sync/commit/c1e756148de0343df66fda1a2380382ef06c16d7)) +* **#477:** :sparkles: add input parameter for pr body ([#488](https://github.com/AndreasAugustin/actions-template-sync/issues/488)) ([481cc21](https://github.com/AndreasAugustin/actions-template-sync/commit/481cc21550d858dfc12c49f4dfb7605ac744a091)) + +## [1.8.1](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.8.0...v1.8.1) (2024-03-02) + + +### Bug Fixes + +* **#476:** :bug: output variable edge cases ([#479](https://github.com/AndreasAugustin/actions-template-sync/issues/479)) ([ab4153b](https://github.com/AndreasAugustin/actions-template-sync/commit/ab4153bb937a2d7ad996f0693977cb943443e8b3)) + +## [1.8.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.7.0...v1.8.0) (2024-02-29) + + +### Features + +* **#472:** :sparkles: define output ([#473](https://github.com/AndreasAugustin/actions-template-sync/issues/473)) ([a19cd8d](https://github.com/AndreasAugustin/actions-template-sync/commit/a19cd8d7c999cdf9bdc2a08818eb2878d1222cdf)) + +## [1.7.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.6.2...v1.7.0) (2024-02-29) + + +### Features + +* **#468:** :sparkles: enable usage of github env variables within hooks ([#469](https://github.com/AndreasAugustin/actions-template-sync/issues/469)) ([17d4603](https://github.com/AndreasAugustin/actions-template-sync/commit/17d4603da56b49e4b72c6531ba6d2db6dbcc3a31)) + +## [1.6.2](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.6.1...v1.6.2) (2024-02-25) + + +### Bug Fixes + +* :bug: try catch for edge cases ([#465](https://github.com/AndreasAugustin/actions-template-sync/issues/465)) ([95ce4e4](https://github.com/AndreasAugustin/actions-template-sync/commit/95ce4e4d5cc72b62970056977256a6592a10547c)) + +## [1.6.1](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.6.0...v1.6.1) (2024-02-25) + + +### Bug Fixes + +* **#461:** :bug: issue with pull request labels with emoji and space ([#462](https://github.com/AndreasAugustin/actions-template-sync/issues/462)) ([89b8d21](https://github.com/AndreasAugustin/actions-template-sync/commit/89b8d210b8454957a81dbbf5b81e6977708a25cd)) + +## [1.6.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.5.0...v1.6.0) (2024-02-22) + + +### Features + +* :sparkles: ([#204](https://github.com/AndreasAugustin/actions-template-sync/issues/204)) gpg sign ([#436](https://github.com/AndreasAugustin/actions-template-sync/issues/436)) ([99aefe5](https://github.com/AndreasAugustin/actions-template-sync/commit/99aefe5830f9ee249bbfbd90a85108f76e897c33)) + +## [1.5.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.4.0...v1.5.0) (2024-02-04) + + +### Features + +* :sparkles: ([#401](https://github.com/AndreasAugustin/actions-template-sync/issues/401)) add option to force file deletion ([#435](https://github.com/AndreasAugustin/actions-template-sync/issues/435)) ([e68941f](https://github.com/AndreasAugustin/actions-template-sync/commit/e68941ff0fc9695be3fe480ab739ebeb318dca0d)) + +## [1.4.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.3.0...v1.4.0) (2024-01-25) + + +### Features + +* allow for pruning of older PRs ([#438](https://github.com/AndreasAugustin/actions-template-sync/issues/438)) ([0e51714](https://github.com/AndreasAugustin/actions-template-sync/commit/0e51714bd42e4ce8223a641d7435c220a99aad51)) + +## [1.3.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.2.0...v1.3.0) (2024-01-18) + + +### Features + +* **hooks:** added precommit hook ([#439](https://github.com/AndreasAugustin/actions-template-sync/issues/439)) ([4a42410](https://github.com/AndreasAugustin/actions-template-sync/commit/4a42410a3c63b359844b20860359bc2f8ab4e6fa)) + +## [1.2.0](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.1.9...v1.2.0) (2024-01-06) + + +### Features + +* :construction_worker: ([#432](https://github.com/AndreasAugustin/actions-template-sync/issues/432)) support major/minor tags ([#433](https://github.com/AndreasAugustin/actions-template-sync/issues/433)) ([eb942cf](https://github.com/AndreasAugustin/actions-template-sync/commit/eb942cf9366ff4cfbcb6860f9392db555a4e5c11)) + +## [1.1.9](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.1.8...v1.1.9) (2023-12-30) + + +### Bug Fixes + +* github pat in documentation examples ([#423](https://github.com/AndreasAugustin/actions-template-sync/issues/423)) ([aea6128](https://github.com/AndreasAugustin/actions-template-sync/commit/aea6128ca5ae7e21f7ba687ead3f56326cce1b76)) + +## [1.1.8](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.1.7...v1.1.8) (2023-09-24) + + +### Bug Fixes + +* **ci:** :bug: issues within ci ([2793a56](https://github.com/AndreasAugustin/actions-template-sync/commit/2793a56cecdd0000c25e0a81972d78a45fbb4d97)) + +## [1.1.7](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.1.6...v1.1.7) (2023-09-24) + + +### Bug Fixes + +* **ci:** :bug: ([#388](https://github.com/AndreasAugustin/actions-template-sync/issues/388)) issues within ci ([8649015](https://github.com/AndreasAugustin/actions-template-sync/commit/8649015f18ab9855f8d3b93c50d67444438bb14f)) + +## [1.1.6](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.1.5...v1.1.6) (2023-09-24) + + +### Bug Fixes + +* **ci:** :bug: ([#388](https://github.com/AndreasAugustin/actions-template-sync/issues/388)) issues within ci ([dd57314](https://github.com/AndreasAugustin/actions-template-sync/commit/dd573140ec37a0e41ff179af7d9954a049c9eb93)) + +## [1.1.5](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.1.4...v1.1.5) (2023-09-24) + + +### Bug Fixes + +* **ci:** :bug: ([#388](https://github.com/AndreasAugustin/actions-template-sync/issues/388)) issues within ci ([e063b29](https://github.com/AndreasAugustin/actions-template-sync/commit/e063b29c03ebb93b4185b752f4d8dc61db3605df)) +* **ci:** :bug: ([#387](https://github.com/AndreasAugustin/actions-template-sync/issues/387)) issue with docker push ([#392](https://github.com/AndreasAugustin/actions-template-sync/issues/392)) ([a94785c](https://github.com/AndreasAugustin/actions-template-sync/commit/a94785c1d4150fac0168410757004e83f638caf1)) + +## [1.1.4](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.1.3...v1.1.4) (2023-09-24) + + +### Bug Fixes + +* **docs:** :bug: ([#387](https://github.com/AndreasAugustin/actions-template-sync/issues/387)) fix missing documentation about .templatesyncignore paths ([3130f5b](https://github.com/AndreasAugustin/actions-template-sync/commit/3130f5bc62a6f98ece2c209994283520fe3ca811)) + +## [1.1.3](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.1.2...v1.1.3) (2023-09-16) + + +### Bug Fixes + +* :bug: ([#380](https://github.com/AndreasAugustin/actions-template-sync/issues/380)) small fix related to remote file mode changes ([#383](https://github.com/AndreasAugustin/actions-template-sync/issues/383)) ([ff25f8c](https://github.com/AndreasAugustin/actions-template-sync/commit/ff25f8cbcd237716eeff23dc5616632c7663e99f)) + +## [1.1.2](https://github.com/AndreasAugustin/actions-template-sync/compare/v1.1.1...v1.1.2) (2023-09-03) + + +### Bug Fixes + +* :bug: ([#375](https://github.com/AndreasAugustin/actions-template-sync/issues/375)) fix edge case with .templatesyncignore ([#378](https://github.com/AndreasAugustin/actions-template-sync/issues/378)) ([1eede30](https://github.com/AndreasAugustin/actions-template-sync/commit/1eede30772357d6984d1757753a672da4119d356)) diff --git a/third_party/AndreasAugustin/actions-template-sync/CITATION.cff b/third_party/AndreasAugustin/actions-template-sync/CITATION.cff new file mode 100644 index 00000000..2c6dc413 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/CITATION.cff @@ -0,0 +1,26 @@ +# This CITATION.cff file was generated with cffinit. +# Visit https://bit.ly/cffinit to generate yours today! + +cff-version: 1.2.0 +title: github-action-template-sync +message: >- + If you use this software, please cite it using the + metadata from this file. +type: software +authors: + - given-names: Andreas + family-names: Augustin + orcid: 'https://orcid.org/0009-0003-8658-2370' +repository-code: 'https://github.com/AndreasAugustin/actions-template-sync' +url: 'https://andreasaugustin.github.io/actions-template-sync/' +abstract: >- + Synchronise git repositories in an automated manner. + Different git providers like GitHub (enterprise), + GitLab,.. are supported as the source provider. This can + help you e.g. for migration from another git provider to + GitHub or if you want to mirror git repositories. +keywords: + - github + - repo-sync +license: MIT +version: v0.8.0 diff --git a/third_party/AndreasAugustin/actions-template-sync/Dockerfile b/third_party/AndreasAugustin/actions-template-sync/Dockerfile new file mode 100644 index 00000000..79c5e571 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/Dockerfile @@ -0,0 +1,71 @@ +######################################## +# prod image +####################################### +FROM alpine:3.22.0 AS prod + +ARG GH_CLI_VER=2.44.1 + +# TODO(anau) change user +ARG GITHUB_URL="https://github.com/AndreasAugustin/actions-template-sync" + +# https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys +LABEL org.opencontainers.image.url="${GITHUB_URL}" +LABEL org.opencontainers.image.documentation="${GITHUB_URL}/README.md" +LABEL org.opencontainers.image.source="${GITHUB_URL}" +LABEL org.opencontainers.image.licenses="MIT" +LABEL org.opencontainers.image.authors="andyAugustin" +LABEL org.opencontainers.image.title="actions-template-sync image" +LABEL org.opencontainers.image.description="contains actions-template-sync" + +# install packages +RUN apk add --update --no-cache bash git curl musl openssh git-lfs yq gnupg + +RUN wget https://github.com/cli/cli/releases/download/v${GH_CLI_VER}/gh_${GH_CLI_VER}_linux_386.tar.gz -O ghcli.tar.gz +RUN tar --strip-components=1 -xf ghcli.tar.gz + +ADD src/*.sh /bin/ +RUN chmod +x /bin/entrypoint.sh \ + && chmod +x /bin/sync_template.sh \ + && chmod +x /bin/sync_common.sh \ + && chmod +x /bin/gpg_no_tty.sh + +RUN mkdir -p /root/.ssh \ + && ssh-keyscan -t rsa github.com >> /root/.ssh/known_hosts + +ENTRYPOINT ["/bin/bash", "/bin/entrypoint.sh"] +####################################### +# image for dev build environment +###################################### +FROM prod AS dev + +# install packages +RUN apk add --update --no-cache make zsh tmux vim tig + +# Make zsh your default shell for tmux +RUN echo "set-option -g default-shell /bin/zsh" >> /root/.tmux.conf + +# install oh-my-zsh +RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" + +WORKDIR /app + +ENTRYPOINT ["/bin/zsh"] + +####################################### +# image for creating the documentation +###################################### +FROM node:24.4.0-alpine AS docs + +# install packages +RUN apk add --update --no-cache bash make git zsh curl tmux + +# Make zsh your default shell for tmux +RUN echo "set-option -g default-shell /bin/zsh" >> /root/.tmux.conf + +# install oh-my-zsh +RUN sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" + +# install quality gate +RUN npm install -g markdownlint-cli + +WORKDIR /app diff --git a/third_party/AndreasAugustin/actions-template-sync/LICENSE b/third_party/AndreasAugustin/actions-template-sync/LICENSE new file mode 100644 index 00000000..325b8d7d --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 andy Augustin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/AndreasAugustin/actions-template-sync/Makefile b/third_party/AndreasAugustin/actions-template-sync/Makefile new file mode 100644 index 00000000..6a91414c --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/Makefile @@ -0,0 +1,38 @@ +SHELL := /bin/bash +.DEFAULT_GOAL := help + +########################### +# VARIABLES +########################### + +########################### +# MAPPINGS +########################### + +########################### +# TARGETS +########################### + +.PHONY: help +help: ## help target to show available commands with information + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: markdownlint +markdownlint: ## Validate markdown files + docker compose run docs markdownlint . + +.PHONY: zsh +zsh: ## open dev container with build environment + docker compose run --service-ports dev + +.PHONY: prod +prod: ## run the prod docker image with bash + docker compose run prod + +.PHONY: prune +prune: ## delete the whole environment + docker compose down -v --rmi all --remove-orphans + +.Phony: shellcheck +shellcheck: ## run shellcheck + docker compose run shellcheck -x src/*.sh diff --git a/third_party/AndreasAugustin/actions-template-sync/README.md b/third_party/AndreasAugustin/actions-template-sync/README.md new file mode 100644 index 00000000..80c80048 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/README.md @@ -0,0 +1,862 @@ +# actions-template-sync + +[![All Contributors](https://img.shields.io/badge/all_contributors-38-orange.svg?style=flat-square)](#contributors-) + + + [![actions-template-sync](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/actions_template_sync.yml/badge.svg)](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/actions_template_sync.yml) + +[![Lint](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/lint.yml/badge.svg)](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/lint.yml) + +[![shellcheck](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/shellcheck.yml/badge.svg)](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/shellcheck.yml) + +[![test](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/test.yml/badge.svg)](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/test.yml) + +[![test-hooks](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/test_hooks.yml/badge.svg)](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/test_hooks.yml) + +[![test-ssh](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/test_ssh.yml/badge.svg)](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/test_ssh.yml) + +[![test-ssh-gitlab](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/test_ssh_gitlab.yml/badge.svg)](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/test_ssh_gitlab.yml) + +[![push-docker](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/push_docker.yml/badge.svg)](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/push_docker.yml) + +[![gh-pages-mk-docs](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/gh_pages_mk_docs.yml/badge.svg)](https://github.com/AndreasAugustin/actions-template-sync/actions/workflows/gh_pages_mk_docs.yml) + +## abstract + +Synchronise git repositories in an automated manner. Different git providers like GitHub (enterprise), GitLab,.. are supported as the source provider. +This can help you e.g. for migration from another git provider to GitHub or if you want to mirror git repositories. + +### History + +It is possible to create repositories within Github with +[GitHub templates](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-template-repository). +This is a nice approach to have some boilerplate within your repository. +Over time, the template repository will get some code changes. +The problem is that the already created repositories won't know about those changes. +This GitHub action will help you to keep track of the template changes. +The initial author of this repository faced that issue several times and decided to write a GitHub action to face that issue. +Because of the nice community, several feature requests helped to go on with the development of the action. Now several other features are supported. + +## Features + +This action is creating a pull request with the latest changes within the target repo whenever it runs with following exceptions + +* there is already an open PR created with the latest changes of the source repository. + * if there are new changes and a PR is already open, a new PR will be created (option to clean up older PRs) +* related new changes are ignored within the `.templatesyncignore` file +* the source repository is fully included within the target repository + +```mermaid +flowchart LR + github_source("fa:fa-github GitHub source repository [private|public]") + gitlab_source("fa:fa-gitlab GitLab source repository [private|public]") + any_source("fa:fa-git Any git provider [private|public]") + github_target{{"fa:fa-github GitHub target repository [private|public]"}} + github_source --> |"ssh | PAT | github app"| github_target + gitlab_source --> |"ssh"| github_target + any_source --> |"ssh"| github_target +``` + +* Sync other public or private repository (e.g. template repositories) with the current repository +* Ignore files and folders from syncing using a `.templatesyncignore` file +* many configuration options +* different lifecycle hooks are supported. This opens the possibility to inject custom code into the workflow with a yaml definition file. +* different git provider like GitLab, Gittea,.. as source are supported (with ssh). + See [.github/workflows/test_ssh_gitlab.yml](.github/workflows/test_ssh_gitlab.yml) for an example. +* It is not necessarily needed that source and target repository have the same base history. + Because of that reason, it is possible to merge 2 totally different repositories with the help of the action. + +## Usage + +Usage changes depending on whether the template repository is public or private, regardless of the visibility of the current repository. + +### Public template repository + +Add this configuration to a GitHub action in the current repository: + +```yaml +# File: .github/workflows/template-sync.yml + +on: + # cronjob trigger + schedule: + - cron: "0 0 1 * *" + # manual trigger + workflow_dispatch: +jobs: + repo-sync: + runs-on: ubuntu-latest + # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs + permissions: + contents: write + pull-requests: write + + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + # https://github.com/actions/checkout#usage + # uncomment if you use submodules within the repository + # with: + # submodules: true + + - name: actions-template-sync + uses: AndreasAugustin/actions-template-sync@v2 + with: + source_repo_path: + upstream_branch: # defaults to main + pr_labels: ,[,...] # defaults to template_sync +``` + +You will receive a pull request within your repository if there are some changes available in the template. + +### Private template repository + +If your current repository was created from a private template, there are several possibilities. + +#### 1. Using a GitHub app + +You can create and use a [GitHub App][github-app] to handle access to the private template repository. +To generate a token for your app you can use a separate action like [tibdex/github-app-token][github-app-token]. +You have to set up the checkout step with the generated token as well. + +```yaml +jobs: + repo-sync: + runs-on: ubuntu-latest + + steps: + - name: Generate token to read from source repo # see: https://github.com/tibdex/github-app-token + id: generate_token + # https://github.com/tibdex/github-app-token + uses: tibdex/github-app-token@v2 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.PRIVATE_KEY }} + + - name: Checkout + # https://github.com/actions/checkout#usage + uses: actions/checkout@v4 + with: + # submodules: true + token: ${{ steps.generate_token.outputs.token }} + + - name: actions-template-sync + uses: AndreasAugustin/actions-template-sync@v2 + with: + source_gh_token: ${{ steps.generate_token.outputs.token }} + source_repo_path: + upstream_branch: # defaults to main + pr_labels: ,[,...] # defaults to template_sync +``` + +#### 2. Using SSH + +You have various options to use ssh keys with GitHub. +An example is [deployment keys][deployment-keys]. For our use case, write permissions are not needed. +Within the current repository, where the GitHub action is enabled, add a secret +(e.q. `SOURCE_REPO_SSH_PRIVATE_KEY`) with the content of your private SSH key. +Make sure that the read permissions of that secret fulfill your use case. +Set the optional `source_repo_ssh_private_key` input parameter. +It is also possible to use a different git provider, e.g. GitLab. + +```yaml +jobs: + repo-sync: + runs-on: ubuntu-latest + # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs + permissions: + contents: write + pull-requests: write + + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + # https://github.com/actions/checkout#usage + uses: actions/checkout@v4 + with: + # submodules: true + token: ${{ secrets.GITHUB_TOKEN }} + + - name: actions-template-sync + uses: AndreasAugustin/actions-template-sync@v2 + with: + source_gh_token: ${{ secrets.GITHUB_TOKEN }} + source_repo_path: ${{ secrets.SOURCE_REPO_PATH }} # , should be within secrets + upstream_branch: ${{ secrets.TARGET_BRANCH }} # # defaults to main + pr_labels: ,[,...] # defaults to template_sync + source_repo_ssh_private_key: ${{ secrets.SOURCE_REPO_SSH_PRIVATE_KEY }} # contains the private ssh key of the private repository +``` + +#### 3. Using a PAT + +:warning: when the source repository is private using PATs, also the target repository must be private. +Else it won't work. + +[Personal access token][github-pat] is an alternative to using passwords for authentication to GitHub. +You can add a kind of password to your GitHub account. The PAT needs a scope. +We need different scopes for the source and target repo. + +##### a. Source repo + +The workflow needs read access to the source repo. + +You need to set the scopes to read the source repo. + +###### Fine grained source repo + +* `contents` -> read +* `metadata` -> read + +###### Classic source repo + +* `repo` -> all +* `read:org` + +![pat-scopes](docs/assets/pat_needed_scopes_source_repo.png) + +###### General source repo + +Furthermore, you need to set the access within the source repository to allow GitHub actions within the target repository. +As mentioned before (you can see the note in the image) you need to set the target repository to private. +settings -> actions -> general. + +![pat-source-repo-access](docs/assets/pat_needed_access_source_repo.png) + +##### b. Target repo + +###### Fine grained target repo + +* `contents` -> write +* `metadata` -> read +* `pull requests` -> write + +If you are automatically adding reviewers you also need + +* `organisation:members` read permissions to the PAT token. + +![pat-scopes-fine-grained](docs/assets/pat_fine_grained_needed_scopes.png) + +###### Classic target repo + +When the action detects any changes, it will create a new branch and will push the updates to this branch. +When no files are changed in the `.github/workflows` directory, this works well with the default `${{ github.token }}` token. +This token does however not have `workflow` scope and can therefore not make any changes to these files. +For this purpose a token must be created with the following scope as depicted in the figure below. + +* `workflow` -> will also enable `repo` +* `admin:read` + ![pat-scopes](docs/assets/pat_needed_scopes_target_repo.png) + +example workflow definition +:warning: to the checkout action you need to add the parameter `persist-credentials: false` or you will most likely face an issue (#557 #627) + +```yml +name: actions-template-sync + +on: + # cronjob trigger At 00:00 on day-of-month 1. https://crontab.guru/every-month + schedule: + - cron: "0 0 1 * *" + # manual trigger + workflow_dispatch: + +jobs: + test-implementation-job: + + runs-on: ubuntu-latest + + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + with: + # submodules: true + token: ${{ secrets.CUSTOM_GITHUB_PAT }} + persist-credentials: false # needed see #557 and #627 + + - name: Test action step PAT + uses: AndreasAugustin/actions-template-sync@v2 + with: + source_gh_token: ${{ secrets.CUSTOM_GITHUB_PAT }} + source_repo_path: ${{ secrets.SOURCE_REPO_PATH }} # , should be within secrets +``` + +### Action Inputs + +| Variable | Description | Required | Default | +|-----------------------------|---------------------------------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------| +| github_token | :warning: [Deprecated] please use `source_gh_token` instead to have a declarative name. Token for the repo. Can be passed in using `${{ secrets.GITHUB_TOKEN }}` | `true` | `${{ github.token }}` | +| source_gh_token | `[optional]` used for the source github repo token. Can be passed in using `${{ secrets.GITHUB_TOKEN }}` | `false` | `${{ github.token }}` | +| target_gh_token | `[optional]` used for the source github repo token. Can be passed in using `${{ secrets.GITHUB_TOKEN }}` | `false` | `${{ github.token }}` | +| source_repo_path | Repository path of the template | `true` | | +| upstream_branch | The target branch | `false` | The remote's default (usually `main`) | +| source_repo_ssh_private_key | `[optional]` private ssh key for the source repository. [see](#private-template-repository) | `false` | | +| pr_branch_name_prefix | `[optional]` the prefix of branches created by this action | `false` | `chore/template_sync` | +| pr_title | `[optional]` the title of PRs opened by this action. Must be already created. | `false` | `upstream merge template repository` | +| pr_body | `[optional]` the body of PRs opened by this action. | `false` | `Merge ${SOURCE_REPO} ${TEMPLATE_GIT_HASH}` | +| pr_labels | `[optional]` comma separated list. [pull request labels][pr-labels]. | `false` | `sync_template` | +| pr_reviewers | `[optional]` comma separated list of pull request reviewers. | `false` | | +| pr_commit_msg | `[optional]` commit message in the created pull request | `false` | `chore(template): merge template changes :up:` | +| hostname | `[optional]` the hostname of the repository | `false` | `github.com` | +| is_git_lfs | `[optional]` set to `true` if you want to enalbe git lfs | `false` | `false` | +| is_dry_run | `[optional]` set to `true` if you do not want to push the changes and not want to create a PR | `false` | | +| is_allow_hooks | `[optional]` set to `true` if you want to enable lifecycle hooks. Use this with caution! | `false` | `false` | +| hooks | `[optional]` please check the lifecycle hooks section below | `false` | | +| is_force_push_pr | `[optional]` set to `true` if you want to force push and pr update. Needs further permissions (see below) | `false` | `false` | +| is_pr_cleanup | `[optional]` set to `true` if you want to cleanup older PRs targeting the same branch. Use this with caution! | `false` | `false` | +| is_keep_branch_on_pr_cleanup | `[optional]` set to `true` if you want to keep the branch when pr is cleanup. Only makes sense together with `is_pr_cleanup` | `false` | `false` | +| is_not_source_github | `[optional]` set to `true` if the source git provider is not GitHub | `false` | `false` | +| is_force_deletion | `[optional]` set to `true` if you want to force delete files which are deleted within the source repository even if they contain changes. You need to also adjust `git_remote_pull_params` (see below for details) | `false` | `false` | +| git_user_name | `[optional]` set the committer git user.name | `false` | `${GITHUB_ACTOR}` | +| git_user_email | `[optional]` set the committer git user.email | `false` | `github-action@actions-template-sync.noreply.${SOURCE_REPO_HOSTNAME}` | +| git_remote_pull_params | `[optional]` set remote pull parameters | `false` | `--allow-unrelated-histories --squash --strategy=recursive -X theirs` | +| gpg_private_key | `[optional]` set if you want to sign commits | `false` | | +| gpg_passphrase | `[optional]` set if your optional gpg private key has a passphrase | `false` | | +| steps | `[optional] add the steps you want to execute within the action` | `false` | all steps will be executed | +| template_sync_ignore_file_path | `[optional] set the path to the ignore file.` | false |`.templatesyncignore` | +| is_with_tags | `[optional]` set to `true` if tags should be synced | `false` | `false` | + +### Action Outputs + +> Properties that are available after the action executed. + +| output | description | +| ------ | ----------- | +| pr_branch | The name of the branch used for the pull request | +| template_git_hash | The template source repository git hash | + +**Remarks** Please consider following edge cases + +* **pr_branch** + * If PR branch already exists (e.g. after a 2nd run) the action won't update the branch but will still output the branch name + * If the remote repository already contains the source repository changes the action will exit and the output variable will be undefined + * If there are no changes the action will exit and the output variable will be undefined + +### Change the target branch + +Per default the action is using the default branch as the target. To change this behaviour just add it to the checkout action + +```yaml + - name: Checkout + uses: actions/checkout@v4 + with: + ref: # defaults to the default branch +``` + +### Docker + +There are docker images available. Please checkout [How to use docker](docs/DOCKER.md) for details. + +* [dockerhub andyaugustin/actions-template-sync][dockerhub-repo] +* [github andreasaugustin/actions-template-sync][github-repo] + +### Example + +This repo uses this [template][template] and this action from the [marketplace][marketplace]. +See the definition within [self-usage][self-usage]. + +If you look for a more detailed guide you can have a look at + +* [Dev.to][devto-example] +* [GitHub][github-example] +* :heart: [nice blog post][dotdc-blog] + +### Trigger + +You can use all [triggers][action-triggers] which are supported for GitHub actions + +## Ignore Files + +Create a `.templatesyncignore` file. Just like writing a `.gitignore` file, follow the [glob pattern][glob-pattern] +in defining the files and folders that should be excluded from syncing with the template repository. + +It can also be stored inside `.github` folder. + +The `template_sync_ignore_file_path` parameter allows you to specify a path to an ignore file. This variable defaults to `.templatesyncignore`. +Changing this allows you to support template sync with more than one repository using different ignore files. + +The action will look for the path specified within `.` or `.github/` + +_Note: It is not possible to sync also the `.templatesyncignore` itself. Any changes from the template repository will be restored automatically._ + +**Remark** reading the [gitglossary][git-glossary] (_pathspec_ section) you see a slight difference to the `.gitignore` file +when you like to disable files you need to use `:!`. +E.g. when you like to disable the sync for all files with exceptions, you need to do smth like + +```txt +:!newfile-1.txt +* +``` + +## Force Push and PR + +If you set the input `is_force_push_pr` to `true` you are able to react to e.g. metadata changes within the workflow definition file. +Please note that you need to add permissions for `repository-projects: read`. Compare the needed scope with [gh pr edit][github-gh-cli-pr-edit] + +```yaml + permissions: + contents: write + pull-requests: write + repository-projects: read +``` + +## Sign commits + +It is recommended to [sign your commits][devto-sign-commits]. This action is able to sign commits. + +First, [generate a GPG key][github-create-gpg-key] and export the GPG private key as an ASCII armored version to your clipboard: + +```bash +# macOS +gpg --armor --export-secret-key jon@doe.example | pbcopy + +# Ubuntu (assuming GNU base64) +gpg --armor --export-secret-key jon@doe.example -w0 | xclip + +# Arch +gpg --armor --export-secret-key jon@doe.example | xclip -selection clipboard -i + +# FreeBSD (assuming BSD base64) +gpg --armor --export-secret-key jon@doe.example | xclip +``` + +:warning: the gpg username and email must match the `git_user_name` and `git_user_email` parameters. +Paste your clipboard as a [secret][github-create-secret] named `GPG_PRIVATE_KEY` for example. +If your key has a password, create another secret named `GPG_PASSPHRASE`. + +```yaml +# File: .github/workflows/template-sync.yml + +on: + # cronjob trigger + schedule: + - cron: "0 0 1 * *" + # manual trigger + workflow_dispatch: +jobs: + repo-sync: + runs-on: ubuntu-latest + # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs + permissions: + contents: write + pull-requests: write + + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + + - name: actions-template-sync + uses: AndreasAugustin/actions-template-sync@v2 + with: + source_gh_token: ${{ secrets.GITHUB_TOKEN }} + source_repo_path: + git_user_name: # add the gpg username + git_user_email: # add the gpg email + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + # uncomment if your key has a passphrase + # gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }} + +``` + +## Lifecycle actions + +The action has different phases which are executed in the following order + +* **preparation** prepare and configure git related things + * init git + * auth related (ssh or github auth) + * [optional] gpg setup +* **prechecks** run some prechecks + * skipped if `is_force_push_pr` parameter is set to `true` + * check if the sync branch is already existing in target repository + * check if new changes of the source repository are already within history +* **pull** pull the changes from the remote repository into the action runtime +* **commit** commit the changes within the action runtime +* **push** + * if `is_force_push_pr` is set to true then a force push will be executed +* **pr** + * eventual create registered labels (:ninja: emojis are supported) + * create a new PR + * if `is_force_push_pr` is set to true then the PR will be created or edited + * [optional] **cleanup** eventual cleanup older PRs of the action +* set **github action outputs** + +If `is_dry_run` parameter is set to true then all stages modifying the github state are not run (e.g. push, cleanup and pr). + +It is possible to run a subset of the mentioned lifecycle actions. +**preparation** and **github action outputs** will be run every time. + +:warning: Advanced feature. Use with care (possibly set `is_dry_run: true` configuration parameter for testing purposes) + +e.g. + +```yaml +# File: .github/workflows/test_steps.yml + +on: + # cronjob trigger + schedule: + - cron: "0 0 1 * *" + # manual trigger + workflow_dispatch: +jobs: + repo-sync: + runs-on: ubuntu-latest + # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs + permissions: + contents: write + pull-requests: write + + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + + - name: actions-template-sync first steps + uses: AndreasAugustin/actions-template-sync@v2 + with: + source_repo_path: + steps: "prechecks,pull" # order matters + + - name: in between step + run: | + echo "I can do whatever I want" + git status + + - name: actions-template-sync next steps + uses: AndreasAugustin/actions-template-sync@v2 + with: + source_repo_path: + steps: "commit,push,pr" # order matters + +``` + +## Lifecycle hooks + +Different lifecycle hooks are supported. You need to enable the functionality with the option `is_allow_hooks` and set it to `true` +:warning: use this functionality with caution. You can use one of the available docker images to test it out. **With great power comes great responsibility**. + +In addition, you need either a configuration file with the name `templatesync.yml` within the root of the target repository +or you set the hooks input parameter within the action definition with a related yaml string + +The following hooks are supported (please check [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for a better understanding of the lifecycles). + +* `prepull` is executed before the code is pulled from the source repository +* `precommit` is executed before the code is commited +* `prepush` is executed before the push is executed, right after the commit +* `precleanup` is executed before older PRs targeting the same branch are closed +* `prepr` is executed before the PR is done + +**Remark** If you need to install aditional tools just install them in an additional step upfront the action invokation. +If using the docker image the underlying OS is defined by an Alpine container. + +### Example for the hooks input parameter + +```yml +- name: Test action step + uses: AndreasAugustin/actions-template-sync@v2 + env: + MY_VAR: "foo" # possible to define envrionment variables + with: + source_repo_path: AndreasAugustin/template.git + upstream_branch: main + is_dry_run: true + is_allow_hooks: true + hooks: > + prepull: + commands: + - echo 'hi, we are within the prepull phase' + - echo 'maybe you want to do adjustments on the local code' +``` + +### Schema and example for the `templatesync.yml` + +**Remark** It is possible to use environment variables within the github action definition usable within the command configuration, e.g. + +```yml +- name: Test action step + uses: AndreasAugustin/actions-template-sync@v2 + with: + source_repo_path: AndreasAugustin/template.git + upstream_branch: main + is_dry_run: true + is_allow_hooks: true +``` + +Please not the double quotes within the following `prepull echo` command + +```yml +hooks: + prepull: + commands: + - echo "hi, we are within the prepull phase ${MY_VAR}" + - echo 'maybe you want to do adjustments on the local code' + precommit: + commands: + - echo 'hi, we are within the precommit phase' + - echo 'maybe you want to add further changes before the code is committed' + prepush: + commands: + - echo 'hi, we are within the prepush phase' + - echo 'maybe you want to add further changes and commits' + precleanup: + commands: + - echo 'hi, we are within the precleanup phase' + - echo 'maybe you want to interact with older PRs before they are closed' + prepr: + commands: + - echo 'hi, we are within the prepr phase' + - echo 'maybe you want to change the code a bit and do another push before creating the pr' +``` + +## Labels creation + +By default, generated PRs will be labeled with the `template_sync` label. +If that label doesn't exist in your repository, it will be created automatically unless you specify your own existing labels. +Associating a label with the generated PRs helps keeping track of them and allows for features like automatic PR cleanup. + +## Pull request cleanup + +Depending on your way of working, you may end up with multiple pull requests related to template syncing pointing to the same branch. +If you want to avoid this situation, you can instruct this action to clean up older PRs (search based on labels defined with the `pr_labels` config parameter). + +:warning: this feature will close all pull requests with labels configured with `pr_labels` config parameter. + +## Force deletion + +This feature will force delete files if those are deelted within the source repository. + +:warning: it is highly related to the `git_remote_pull_params` config parameter and won't work with the default. +You need to change the default one e.g. to `git_remote_pull_params: --allow-unrelated-histories --strategy=recursive --no-edit`. + +## GHES and custom runners + +Some notes if you use GitHub Enterprise Server (GHES) and/or custom runners. +The action script is based on bash. That means your runner must be able to run bash scripts. +Furthermore you need to have the following command line tools installed: + +* ssh +* [GitHub cli][gh-cli] +* git +* optional (dependent the features you are using) + * [git lfs][git-lfs] if you are using the lfs functionality + * [yq][yq] if you are using the hook functionality + * gpg if you are using the git signing functionality + +Furthermore most likely you have a custom domain name. Therefore you should configure the `hostname` GitHub action parameter. + +### Remark + +:whale: There is also a docker image available which has all needed tools installed. This is helpful e.g. if you are not able to use a remote action. +The idea is to use the [docker action][action-docker] + +* [GitHub registry][github-repo] +* [Dockerhub registry][dockerhub-repo] + +## Troubleshooting + +* The error message `refusing to allow a GitHub App to create or update workflow '.github/workflows/.yml' without 'workflows' permission)` +is indicating that the PAT in the `target_gh_token` does not have the correct permissions. +This happens because the template repository is trying to overwrite some files inside `.github/workflows/`. + + Currently `GITHUB_TOKEN` can't be given `workflow` permission. + You can grant our workflow with `workflow` permission using a PAT following the steps below: + + 1. [Create a PAT][github-create-pat] with these repository permissions granted: `workflow`. + + 2. Copy the generated token and [create a new secret for your target repository][github-create-secret]. + + 3. Configure the `actions-template-sync` step to use the freshly generated token in `target_gh_token` like this: + + ```yaml + # File: .github/workflows/template-sync.yml + + on: + # cronjob trigger + schedule: + - cron: "0 0 1 * *" + # manual trigger + workflow_dispatch: + jobs: + repo-sync: + runs-on: ubuntu-latest + # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs + permissions: + contents: write + pull-requests: write + + steps: + # To use this repository's private action, you must check out the repository + - name: Checkout + uses: actions/checkout@v4 + with: + # submodules: true + persist-credentials: false # needed + + - name: actions-template-sync + uses: AndreasAugustin/actions-template-sync@v2 + with: + source_gh_token: ${{ secrets.GITHUB_TOKEN }} + target_gh_token: ${{ secrets. }} + source_repo_path: + upstream_branch: # defaults to main + pr_labels: ,[,...] # optional, no default + ``` + + :warning: you need to add `persist-credentials: false` to the checkout action + +* pull request create failed: GraphQL: GitHub Actions is not permitted to create or approve pull requests (createPullRequest) + + Open your project `Settings > Actions > General` and select the checkbox `Allow GitHub Actions to create and approve pull requests` +under the `Workflow permissions` section. + +## Release update notes + +* `v2` + * `git lfs` is no default anymore. Enable with `is_git_lfs` parameter. + * infrastructure change: now using [composite action][action-composite] instead of [docker action][action-docker] + to be more flexible to combine more actions (file system permissions). + * local `git config` now instead of global `git config --global` in respect to be more flexible in chaining actions. +* :warning: starting with version `v1` (`v1.0.0`) the `upstream_branch` variable default is not `main` anymore. It is now set to the remote default branch. +* starting with version v0.5.2-draft the `templateversionrc` file is not needed anymore. You can delete that file from the target repositories. + +## Debug + +You must create a secret named `ACTIONS_STEP_DEBUG` with the value `true` to see the debug messages set by this command in the log. +For more information, see "[Enabling debug logging.][enabling-debug-logging]" + +## Comparison with other tools + +There are other great tools available within GitHub. Here you can find a comparison. + +| **feature** | **actions-template-sync** |[github-sync][other-repo-sync]| [git-repo-sync][other-git-repo-sync] | [action-template-repository-sync][other-action-template-repository-sync] | +| ----------- | ------------------------- | -------------------------- | ------------------------------------ | --------------------------------- | +| GitHub action | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | +| hooks | :heavy_check_mark: | :x: | :x: | :x: | +| available docker image | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | +| sync between private and public repo | :heavy_check_mark: `PAT,ssh,Github app` | :heavy_check_mark: `PAT,ssh` |:x: local repos | :heavy_check_mark: `PAT` | +| sync between 2 private repos | :heavy_check_mark: `PAT,ssh,Github app` | :heavy_check_mark: `PAT,ssh` | :x: local repos | :heavy_check_mark: `PAT` | +| sync between 2 public repos | :heavy_check_mark: | :heavy_check_mark: | :x: local repos | :heavy_check_mark: | +| two way sync | :x: | :heavy_check_mark: | :x: | :x: | +| Sync from a third-party repo to a Github repo | :heavy_check_mark: | :heavy_check_mark: | :x: local repos | :x: | +| dry run | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | +| ignore files | :heavy_check_mark: | :x: | :x: | :heavy_check_mark: | +| creates a PR | :heavy_check_mark: | :heavy_check_mark: | :x: | :heavy_check_mark: | +| sign commits | :heavy_check_mark: | :x: | :x: | :x: | +| docker images available | :heavy_check_mark: | :x: | :x: | :x: | +| remarks | The action is placed within the target repositories | The action is placed within the target repositories | CLI meant for local use | The action will be based within the base repository with a list of dependent repositories | + +## DEV + +The development environment targets are located in the [Makefile](Makefile) + +```bash +make help +``` + +:ninja: contributiong of any kind are welcome. Please checkout the [contributing guidelines](.github/CONTRIBUTING.md). + +For some architectural notes please have a look at the [docs](./docs/README.md) + +## Contributors ✨ + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
andy Augustin
andy Augustin

πŸ“– πŸ’» πŸ‘€ πŸ›‘οΈ πŸ€” πŸ’¬ πŸ’‘ πŸ–‹ πŸ“ 🚧 πŸš‡ πŸ“¦ ⚠️
Ugo Pattacini
Ugo Pattacini

πŸ“–
Jose Gabrielle Rivera
Jose Gabrielle Rivera

πŸ’»
P.D. Rittenhouse
P.D. Rittenhouse

πŸ€”
Daniel Boll
Daniel Boll

πŸ›
albertschwarzkopf
albertschwarzkopf

πŸ€”
Akul Pillai
Akul Pillai

πŸ›‘οΈ
Stefan Riembauer
Stefan Riembauer

πŸ€”
Fabrizio Cacicia
Fabrizio Cacicia

πŸ›‘οΈ πŸ›
Justin Tunis
Justin Tunis

πŸ€” πŸ’» πŸ›
Michael Matos
Michael Matos

πŸ›
Gavin Williams
Gavin Williams

πŸ€”
Marc Siebeneicher
Marc Siebeneicher

πŸ€” πŸ’» πŸ› πŸ“–
LuΓ­s Henrique A. SchΓΌnemann
LuΓ­s Henrique A. SchΓΌnemann

πŸ€” πŸ“– πŸ’»
George
George

πŸ’¬ πŸ“– πŸ€”
Pedro Rivero
Pedro Rivero

πŸ€”
Eleanor Bronson
Eleanor Bronson

πŸ€”
Marvin Osswald
Marvin Osswald

πŸ“–
David Calvert
David Calvert

πŸ“– πŸ› πŸ’» 🚧 πŸ“
Andy Airey
Andy Airey

πŸ› πŸ‘€
Surya Asriadie
Surya Asriadie

πŸ›
jellllly420
jellllly420

πŸ€” πŸ’¬ πŸ“–
Shaun Tabone
Shaun Tabone

πŸ’»
Kevin AUDE
Kevin AUDE

πŸ€” πŸ’»
Jakob
Jakob

πŸ‘€
Kevin Deldycke
Kevin Deldycke

πŸ› πŸ€” πŸ’»
Jessica Scheick
Jessica Scheick

πŸ›
Gaspar Melsion
Gaspar Melsion

πŸ€”
Ken Harding
Ken Harding

πŸ’» πŸ›
Jakob Drachmann Havtorn
Jakob Drachmann Havtorn

πŸ€”
Brian
Brian

πŸ“–
MuriloChianfa
MuriloChianfa

πŸ“–
David Snyder
David Snyder

πŸ”¬
Jonathan Østrup
Jonathan Østrup

πŸ€” πŸ’»
Nat Welch
Nat Welch

πŸ› πŸ’»
Pepijn Boer
Pepijn Boer

πŸ› πŸ“–
Alex
Alex

πŸ’» πŸ€” πŸ‘€ ⚠️
yuhengshen
yuhengshen

πŸ› πŸ’»
+ + + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) +specification. Contributions of any kind are welcome! + +[enabling-debug-logging]: https://docs.github.com/en/actions/managing-workflow-runs/enabling-debug-logging +[deployment-keys]: https://docs.github.com/en/developers/overview/managing-deploy-keys#deploy-keys +[action-triggers]: https://docs.github.com/en/actions/reference/events-that-trigger-workflows +[action-composite]: https://docs.github.com/en/actions/creating-actions/creating-a-composite-action +[action-docker]: https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action +[template]: https://github.com/AndreasAugustin/template +[marketplace]: https://github.com/marketplace/actions/actions-template-sync +[self-usage]: https://github.com/AndreasAugustin/actions-template-sync/blob/main/.github/workflows/actions_template_sync.yml +[pr-labels]: https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels +[devto-example]: https://dev.to/andreasaugustin/github-actions-template-sync-1g9k +[devto-sign-commits]: https://dev.to/andreasaugustin/git-how-and-why-to-sign-commits-35dn +[github-example]: https://github.com/AndreasAugustin/teaching/blob/main/docs/git/git_action_sync.md +[github-app]: https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps#about-github-apps +[glob-pattern]: https://en.wikipedia.org/wiki/Glob_(programming) +[github-app-token]: https://github.com/tibdex/github-app-token +[dockerhub-repo]: https://hub.docker.com/r/andyaugustin/actions-template-sync +[github-repo]: https://github.com/AndreasAugustin/actions-template-sync/pkgs/container/actions-template-sync +[github-pat]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token +[other-repo-sync]: https://github.com/repo-sync/github-sync +[other-git-repo-sync]: https://github.com/it3xl/git-repo-sync +[other-action-template-repository-sync]: https://github.com/ahmadnassri/action-template-repository-sync +[git-glossary]: https://git-scm.com/docs/gitglossary +[dotdc-blog]: https://0xdc.me/blog/github-templates-and-repository-sync/ +[github-create-pat]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token +[github-create-secret]: https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#creating-secrets-for-a-repository +[github-create-gpg-key]: https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key +[github-gh-cli-pr-edit]: https://cli.github.com/manual/gh_pr_edit +[gh-cli]: https://github.com/cli/cli +[yq]: https://github.com/mikefarah/yq +[git-lfs]: https://github.com/git-lfs/git-lfs diff --git a/third_party/AndreasAugustin/actions-template-sync/action.yml b/third_party/AndreasAugustin/actions-template-sync/action.yml new file mode 100644 index 00000000..a4029472 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/action.yml @@ -0,0 +1,137 @@ +name: "actions-template-sync" +description: "Synchronises changes of the template repository" +author: "AndreasAugustin" +branding: + icon: cloud + color: green +inputs: + source_gh_token: + description: 'GitHub Token for the repo to be synced from. Can be passed in using $\{{ secrets.GITHUB_TOKEN }}' + required: false + default: ${{ github.token }} + target_gh_token: + description: 'GitHub Token for the repo to be synced to. Can be passed in using $\{{ secrets.GITHUB_TOKEN }}' + required: false + default: ${{ github.token }} + github_token: + deprecationMessage: 'please use source_gh_token instead to have a declarative name' + description: 'GitHub Token for the repo to be synced from. Can be passed in using $\{{ secrets.GITHUB_TOKEN }}' + required: false + source_repo_path: + description: "Repository path of the template" + required: true + upstream_branch: + description: "The target branch" + source_repo_ssh_private_key: + description: "[optional] private ssh key for the source repository. E.q. useful if using a private template repository." + pr_branch_name_prefix: + description: "[optional] the prefix of branches created by this action" + default: "chore/template_sync" + pr_title: + description: "[optional] the title of PRs opened by this action" + default: "upstream merge template repository" + pr_body: + description: "[optional] the body of PRs opened by this action" + pr_labels: + description: "[optional] comma separated list of pull request labels" + default: "template_sync" + pr_reviewers: + description: "[optional] comma separated list of pull request reviewers" + pr_commit_msg: + description: "[optional] the commit message of the template merge" + default: "chore(template): merge template changes :up:" + hostname: + description: "[optional] the hostname of the GitHub repository" + default: "github.com" + is_dry_run: + description: "[optional] set to true if you do not want to push the changes and not want to create a PR" + is_allow_hooks: + description: "[optional] set to true if you want to allow hooks. Use this functionality with caution!" + default: "false" + hooks: + description: "[optional] define the hooks as yaml string input" + is_force_push_pr: + description: "[optional] set to true if you want to force push and pr update" + default: "false" + is_pr_cleanup: + description: "[optional] set to true if you want to cleanup older PRs targeting the same branch." + default: "false" + is_keep_branch_on_pr_cleanup: + description: "[optional] set to true if you want to keep the branch when pr is cleanup" + default: "false" + is_not_source_github: + description: "[optional] set to true if the source repository is not a github related repository. Useful e.q. if the source is GitLab" + default: "false" + is_force_deletion: + description: "[optional] set to true if you want to force delete files which are deleted within the source repository even if they contain changes" + default: "false" + is_git_lfs: + description: "[optional] set to true if you want to enable git lfs" + default: "false" + git_user_name: + description: "[optional] set the committer git user.name for the merge commit" + git_user_email: + description: "[optional] set the committer git user.email for the merge commit" + git_remote_pull_params: + description: "[optional] set the pull parameters for the remote repository" + gpg_private_key: + description: "[optional] set the gpg private key if you want to sign your commits" + gpg_passphrase: + description: "[optional] set if your private gpg key has a password" + steps: + description: "[optional] set the steps to execute within the action" + template_sync_ignore_file_path: + description: "[optional] set the path to the ignore file" + default: ".templatesyncignore" + is_with_tags: + description: "[optional] set to true if tags should be synced" + default: "false" +outputs: + pr_branch: + description: "The name of the PR branch" + value: ${{ steps.sync.outputs.pr_branch }} + template_git_hash: + description: "The git hash of the template source repository" + value: ${{ steps.sync.outputs.template_git_hash }} +runs: + using: "composite" + # image: "src/Dockerfile" + steps: + - name: github sync + run: ${{github.action_path}}/src/entrypoint.sh + # working-directory: src/ + shell: bash + id: sync + env: + SOURCE_GH_TOKEN: ${{ inputs.source_gh_token}} + TARGET_GH_TOKEN: ${{ inputs.target_gh_token }} + # GITHUB_TOKEN is deprecated and will be removed soon + GITHUB_TOKEN: ${{ inputs.github_token }} + # + SOURCE_REPO_PATH: ${{ inputs.source_repo_path }} + UPSTREAM_BRANCH: ${{ inputs.upstream_branch }} + SSH_PRIVATE_KEY_SRC: ${{ inputs.source_repo_ssh_private_key }} + PR_BRANCH_NAME_PREFIX: ${{ inputs.pr_branch_name_prefix }} + PR_TITLE: ${{ inputs.pr_title }} + PR_BODY: ${{ inputs.pr_body }} + PR_LABELS: ${{ inputs.pr_labels }} + PR_REVIEWERS: ${{ inputs.pr_reviewers }} + PR_COMMIT_MSG: ${{ inputs.pr_commit_msg }} + HOSTNAME: ${{ inputs.hostname }} + IS_DRY_RUN: ${{ inputs.is_dry_run }} + IS_ALLOW_HOOKS: ${{ inputs.is_allow_hooks }} + HOOKS: ${{ inputs.hooks }} + IS_FORCE_PUSH_PR: ${{ inputs.is_force_push_pr }} + IS_GIT_LFS: ${{ inputs.is_git_lfs }} + IS_PR_CLEANUP: ${{ inputs.is_pr_cleanup}} + IS_KEEP_BRANCH_ON_PR_CLEANUP: ${{ inputs.is_keep_branch_on_pr_cleanup }} + IS_NOT_SOURCE_GITHUB: ${{ inputs.is_not_source_github }} + IS_FORCE_DELETION: ${{ inputs.is_force_deletion }} + GIT_USER_NAME: ${{ inputs.git_user_name }} + GIT_USER_EMAIL: ${{ inputs.git_user_email }} + GIT_REMOTE_PULL_PARAMS: ${{ inputs.git_remote_pull_params }} + GPG_PRIVATE_KEY: ${{ inputs.gpg_private_key }} + GPG_PASSPHRASE: ${{ inputs.gpg_passphrase }} + STEPS: ${{ inputs.steps }} + TEMPLATE_SYNC_IGNORE_FILE_PATH: ${{ inputs.template_sync_ignore_file_path }} + IS_WITH_TAGS: ${{ inputs.is_with_tags }} diff --git a/third_party/AndreasAugustin/actions-template-sync/docker-compose.yml b/third_party/AndreasAugustin/actions-template-sync/docker-compose.yml new file mode 100644 index 00000000..08f372e8 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/docker-compose.yml @@ -0,0 +1,30 @@ +services: + dev: + build: + context: . + target: dev + volumes: + - .:/app/ + - ~/.gitconfig:/root/.gitconfig:ro + environment: + - SSH_PRIVATE_KEY_SRC + + docs: + build: + context: . + target: docs + volumes: + - .:/app/ + + shellcheck: + image: koalaman/shellcheck:v0.7.2 + volumes: + - .:/app/ + working_dir: /app/ + + prod: + build: + context: . + target: prod + tty: true + entrypoint: ["/bin/bash"] diff --git a/third_party/AndreasAugustin/actions-template-sync/docker-test-config.yml b/third_party/AndreasAugustin/actions-template-sync/docker-test-config.yml new file mode 100644 index 00000000..5da537ab --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/docker-test-config.yml @@ -0,0 +1,6 @@ +schemaVersion: '2.0.0' +commandTests: + - name: "gh is installed" + command: "which" + args: ["gh"] + expectedOutput: ["/bin/gh"] diff --git a/third_party/AndreasAugustin/actions-template-sync/docs/ARCHITECTURE.md b/third_party/AndreasAugustin/actions-template-sync/docs/ARCHITECTURE.md new file mode 100644 index 00000000..843f0ddc --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/docs/ARCHITECTURE.md @@ -0,0 +1,93 @@ +# Architecture + +## abstract + +within this section you will find some information about the code flow + +## Code + +The architecture and logic within the code: + +```mermaid +flowchart TD +Exit[Exit] +Start[Start] +GitHubActionEnv{"fa:fa-github Read GitHubAction env"} + +style Start fill:#f9f,stroke:#333,stroke-width:4px +style Exit fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 + +EnvCheckEntry{Required environment variables exists} +SshCheckEntry{SSH private key defined} +SshConfigureEntry[Configure ssh related variables] +GitConfigureEntry[Configure git global settings] + +EnvCheckSync{Required environment variables exists} +SshConfigureSync[Eventually configure SSH variables] +SetVariablesSync[Set the needed variables, e.q. with reading remote repository] +CheckCommitLocalExistent{"Check if source commit hash is present in target repo"} +GitCheckoutSync["fa:fa-code-branch Create git branch "] +GitPullSync["Pull from remote repository"] +CheckIgnoreFileExistsSync{"Check if .templatesyncignore file exists\n(First inside .github folder, then in root)"} +ResetChangesSync["Reset the changes listed within the ignore file"] +GitCommitSync["fa:fa-code-commit Commit the changes"] + +CheckIsDryRun{"Check if is_dry_run is set to true"} +GitPushSync["Push the changes to GitHub"] +GitPullRequestSync["fa:fa-code-pull-request Create a pull request on GitHub"] +Hook{{"hooks, prepull | precommit | prepush | prepr"}} + +subgraph githubactions["fa:fa-github GitHubActions"] + +Start --> GitHubActionEnv +GitHubActionEnv -->|issues| Exit + + +end + +subgraph entry["entrypoint.sh"] + +GitHubActionEnv -->|all fine| EnvCheckEntry +EnvCheckEntry -->|do not exist| Exit +EnvCheckEntry -->|exist| SshCheckEntry + +SshCheckEntry -->|is defined| SshConfigureEntry +SshCheckEntry -->|is not defined| GitConfigureEntry +SshConfigureEntry --> GitConfigureEntry + +end + + +subgraph sync["sync_template.sh"] +GitConfigureEntry --> EnvCheckSync + +EnvCheckSync -->|do not exist| Exit +EnvCheckSync -->|do exist| SshConfigureSync +SshConfigureSync --> SetVariablesSync + +subgraph compareVersion["Compare the sync version"] +SetVariablesSync --> CheckCommitLocalExistent +CheckCommitLocalExistent -->|commit hash already in target history| Exit +end + +subgraph git["Git Actions"] +CheckCommitLocalExistent -->|commit hash not in target history| GitCheckoutSync +GitCheckoutSync --> GitPullSync +GitPullSync --> CheckIgnoreFileExistsSync +CheckIgnoreFileExistsSync -->|does not exist| GitCommitSync +CheckIgnoreFileExistsSync -->|exists| ResetChangesSync +ResetChangesSync --> GitCommitSync +end + +subgraph github["GitHub Actions"] +GitCommitSync --> CheckIsDryRun +CheckIsDryRun -->|is true| Exit +CheckIsDryRun -->|is not true| GitPushSync +GitPushSync --> GitPullRequestSync +GitPullRequestSync --> Exit + +end + +end + +``` diff --git a/third_party/AndreasAugustin/actions-template-sync/docs/DOCKER.md b/third_party/AndreasAugustin/actions-template-sync/docs/DOCKER.md new file mode 100644 index 00000000..29b7bf24 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/docs/DOCKER.md @@ -0,0 +1,15 @@ +# DOCKER + +## abstract + +If you want to test things out or if you want to build your own action (e.g. in on prem environments) you are able to use docker images. + +- [github registry][github-repo] +- [dockerhub registry][dockerhub-repo] + +## Use the image + +TODO + +[dockerhub-repo]: https://hub.docker.com/r/andyaugustin/actions-template-sync +[github-repo]: https://github.com/AndreasAugustin/actions-template-sync/pkgs/container/actions-template-sync diff --git a/third_party/AndreasAugustin/actions-template-sync/docs/README.md b/third_party/AndreasAugustin/actions-template-sync/docs/README.md new file mode 100644 index 00000000..388074fb --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/docs/README.md @@ -0,0 +1,19 @@ +# Docs + +## abstract + +Within this section you can find some more detailed doumentation. + +```mermaid +flowchart LR + github_source("fa:fa-github GitHub source repository [private|public]") + gitlab_source("fa:fa-gitlab GitLab source repository [private|public]") + any_source("fa:fa-git Any git provider [private|public]") + github_target{{"fa:fa-github GitHub target repository [private|public]"}} + github_source --> |"ssh | PAT | github app"| github_target + gitlab_source --> |"ssh"| github_target + any_source --> |"ssh"| github_target +``` + +- [architecture](./ARCHITECTURE.md) +- [how to use the docker images](./DOCKER.md) diff --git a/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_fine_grained_needed_scopes.png b/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_fine_grained_needed_scopes.png new file mode 100644 index 00000000..41b08903 Binary files /dev/null and b/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_fine_grained_needed_scopes.png differ diff --git a/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_needed_access_source_repo.png b/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_needed_access_source_repo.png new file mode 100644 index 00000000..67cdbd84 Binary files /dev/null and b/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_needed_access_source_repo.png differ diff --git a/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_needed_scopes_source_repo.png b/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_needed_scopes_source_repo.png new file mode 100644 index 00000000..44380e25 Binary files /dev/null and b/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_needed_scopes_source_repo.png differ diff --git a/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_needed_scopes_target_repo.png b/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_needed_scopes_target_repo.png new file mode 100644 index 00000000..f4747549 Binary files /dev/null and b/third_party/AndreasAugustin/actions-template-sync/docs/assets/pat_needed_scopes_target_repo.png differ diff --git a/third_party/AndreasAugustin/actions-template-sync/mkdocs.yml b/third_party/AndreasAugustin/actions-template-sync/mkdocs.yml new file mode 100644 index 00000000..e1e0b24d --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/mkdocs.yml @@ -0,0 +1,11 @@ +site_name: actions-template-sync + +theme: + name: material + +markdown_extensions: + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format diff --git a/third_party/AndreasAugustin/actions-template-sync/src/entrypoint.sh b/third_party/AndreasAugustin/actions-template-sync/src/entrypoint.sh new file mode 100644 index 00000000..f40c4b97 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/src/entrypoint.sh @@ -0,0 +1,235 @@ +#!/usr/bin/env bash +set -e +# set -u +# set -x + +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +# shellcheck source=src/sync_common.sh +source "${SCRIPT_DIR}/sync_common.sh" + +########################################### +# Precheks +########################################## + +if [[ -z "${TARGET_GH_TOKEN}" ]]; then + err "Missing input 'target_gh_token': \${{ secrets.GITHUB_TOKEN }}'."; + exit 1; +fi + +if [[ -z "${SOURCE_GH_TOKEN}" ]]; then + err "Missing input 'source_gh_token': \${{ secrets.GITHUB_TOKEN }}'."; + exit 1; +fi + +if [[ -z "${SOURCE_REPO_PATH}" ]]; then + err "Missing input 'source_repo_path: \${{ input.source_repo_path }}'."; + exit 1 +fi + +if [[ -z "${HOME}" ]]; then + err "Missing env variable HOME."; + exit 1 +fi + +if [[ -z "${GITHUB_SERVER_URL}" ]]; then + err "Missing env variable 'GITHUB_SERVER_URL' of the target github server. E.g. https://github.com" +fi + +if ! [ -x "$(command -v gh)" ]; then + err "github-cli gh is not installed. 'https://github.com/cli/cli'"; + exit 1; +fi + +############################################ +# Variables +############################################ + +DEFAULT_REPO_HOSTNAME="github.com" +export SOURCE_REPO_HOSTNAME="${HOSTNAME:-${DEFAULT_REPO_HOSTNAME}}" +GIT_USER_NAME="${GIT_USER_NAME:-${GITHUB_ACTOR}}" +GIT_USER_EMAIL="${GIT_USER_EMAIL:-github-action@actions-template-sync.noreply.${SOURCE_REPO_HOSTNAME}}" + +# In case of ssh template repository this will be overwritten +SOURCE_REPO_PREFIX="https://${SOURCE_REPO_HOSTNAME}/" + +################################################ +# Functions +################################################ + +####################################### +# doing the ssh setup. +# Arguments: +# ssh_private_key_src +# source_repo_hostname +# Changes: +# SOURCE_REPO_PREFIX +# Exports: +# SRC_SSH_PRIVATEKEY_ABS_PATH +####################################### +function ssh_setup() { + echo "::group::ssh setup" + + info "prepare ssh" + + local src_ssh_file_dir="/tmp/.ssh" + local src_ssh_private_key_file_name="id_rsa_actions_template_sync" + + local ssh_private_key_src=$1 + local source_repo_hostname=$2 + + if [[ -z "${ssh_private_key_src}" ]] &>/dev/null; then + err "Missing variable 'ssh_private_key_src'."; + exit 1; + fi + + if [[ -z "${source_repo_hostname}" ]]; then + err "Missing variable 'source_repo_hostname'."; + exit 1; + fi + + # exporting SRC_SSH_PRIVATEKEY_ABS_PATH to be used later + export SRC_SSH_PRIVATEKEY_ABS_PATH="${src_ssh_file_dir}/${src_ssh_private_key_file_name}" + + debug "We are using SSH within a private source repo" + mkdir -p "${src_ssh_file_dir}" + # use cat <<< instead of echo to swallow output of the private key + cat <<< "${ssh_private_key_src}" | sed 's/\\n/\n/g' > "${SRC_SSH_PRIVATEKEY_ABS_PATH}" + chmod 600 "${SRC_SSH_PRIVATEKEY_ABS_PATH}" + + # adjusting outer variable source repo prefix + SOURCE_REPO_PREFIX="git@${source_repo_hostname}:" + + echo "::endgroup::" +} + +####################################### +# doing the gpg setup. +# Arguments: +# gpg_private_key +# git_user_email +####################################### +function gpg_setup() { + echo "::group::gpg setup" + info "start prepare gpg" + + local gpg_private_key=$1 + local git_user_email=$2 + + if [[ -z "${gpg_private_key}" ]] &>/dev/null; then + err "Missing variable 'gpg_private_key'."; + exit 1; + fi + + if [[ -z "${git_user_email}" ]]; then + err "Missing variable 'git_user_email'."; + exit 1; + fi + + echo -e "${gpg_private_key}" | gpg --import --batch + for fpr in $(gpg --list-key --with-colons "${git_user_email}" | awk -F: '/fpr:/ {print $10}' | sort -u); do echo -e "5\ny\n" | gpg --no-tty --command-fd 0 --expert --edit-key "$fpr" trust; done + + KEY_ID="$(gpg --list-secret-key --with-colons "${git_user_email}" | awk -F: '/sec:/ {print $5}')" + git config user.signingkey "${KEY_ID}" + git config commit.gpgsign true + git config gpg.program "${SCRIPT_DIR}/gpg_no_tty.sh" + + info "done prepare gpg" + echo "::endgroup::" +} + + +####################################### +# doing the git setup. +# Arguments: +# git_user_email +# git_user_name +# source_repo_hostname +####################################### +function git_init() { + echo "::group::git init" + info "set git global configuration" + + local git_user_email=$1 + local git_user_name=$2 + local source_repo_hostname=$3 + + git config user.email "${git_user_email}" + git config user.name "${git_user_name}" + git config pull.rebase false + git config --add safe.directory /github/workspace + + if [[ "${IS_GIT_LFS}" == 'true' ]]; then + info "enable git lfs." + git lfs install + fi + + if [[ "${IS_NOT_SOURCE_GITHUB}" == 'true' ]]; then + info "the source repository is not located within GitHub." + mkdir -p "${HOME}"/.ssh + ssh-keyscan -t rsa "${source_repo_hostname}" >> "${HOME}"/.ssh/known_hosts + else + info "the source repository is located within GitHub." + fi + echo "::endgroup::" +} + +####################################### +# doing the login to the source repository using gh cli +# Arguments: +# source_repo_hostname +####################################### +function gh_login_src_github() { + echo "::group::login src github" + local source_repo_hostname=$1 + # GITHUB_TOKEN is deprecated and can be removed in the future + if [[ -n "${SOURCE_GH_TOKEN}" ]] || [[ -n "${GITHUB_TOKEN}" ]] &>/dev/null; then + ################################ + if [[ -n "${GITHUB_TOKEN}" ]] &>/dev/null; then + warn "github_token parameter is deprecated please use source_gh_token." + info "setting SOURCE_GH_TOKEN" + export SOURCE_GH_TOKEN="${GITHUB_TOKEN}" + unset GITHUB_TOKEN + fi + ############################### + if [[ -z "${SOURCE_GH_TOKEN}" ]] &>/dev/null; then + err "Missing input 'source_gh_token: \${{ secrets.GITHUB_TOKEN }}'."; + exit 1; + fi + info "source server url: ${source_repo_hostname}" + info "logging out" + gh auth logout --hostname "${source_repo_hostname}" || debug "not logged in" + info "login to the source git repository" + gh auth login --git-protocol "https" --hostname "${source_repo_hostname}" --with-token <<< "${SOURCE_GH_TOKEN}" + gh auth status + gh auth setup-git --hostname "${source_repo_hostname}" + gh auth status --hostname "${source_repo_hostname}" + else + info "default token to be used" + gh auth setup-git --hostname "${source_repo_hostname}" + gh auth status --hostname "${source_repo_hostname}" + fi + echo "::endgroup::" +} + +################################################### +# Logic +################################################### + +git_init "${GIT_USER_EMAIL}" "${GIT_USER_NAME}" "${SOURCE_REPO_HOSTNAME}" + +# Forward to /dev/null to swallow the output of the private key +if [[ -n "${SSH_PRIVATE_KEY_SRC}" ]] &>/dev/null; then + ssh_setup "${SSH_PRIVATE_KEY_SRC}" "${SOURCE_REPO_HOSTNAME}" +else + gh_login_src_github "${SOURCE_REPO_HOSTNAME}" +fi + +export SOURCE_REPO="${SOURCE_REPO_PREFIX}${SOURCE_REPO_PATH}" + +if [[ -n "${GPG_PRIVATE_KEY}" ]] &>/dev/null; then + gpg_setup "${GPG_PRIVATE_KEY}" "${GIT_USER_EMAIL}" +fi + +# shellcheck source=src/sync_template.sh +source "${SCRIPT_DIR}/sync_template.sh" diff --git a/third_party/AndreasAugustin/actions-template-sync/src/gpg_no_tty.sh b/third_party/AndreasAugustin/actions-template-sync/src/gpg_no_tty.sh new file mode 100644 index 00000000..63d1c85c --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/src/gpg_no_tty.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +if [[ -n "${GPG_PASSPHRASE}" ]] &>/dev/null; then + gpg --pinentry-mode loopback --batch --yes --passphrase "${GPG_PASSPHRASE}" "$@" <&0 +else + gpg --pinentry-mode loopback --yes --batch "$@" <&0 +fi + +exit $? diff --git a/third_party/AndreasAugustin/actions-template-sync/src/sync_common.sh b/third_party/AndreasAugustin/actions-template-sync/src/sync_common.sh new file mode 100644 index 00000000..3a26f993 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/src/sync_common.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +set -e +# set -u +# set -x + +####################################### +# write a message to STDERR. +# Arguments: +# message to print. +####################################### +function err() { + echo "::error::[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2; +} + +####################################### +# write a debug message. +# Arguments: +# message to print. +####################################### +function debug() { + echo "::debug::$*"; +} + +####################################### +# write a warn message. +# Arguments: +# message to print. +####################################### +function warn() { + echo "::warn::$*"; +} + +####################################### +# write a info message. +# Arguments: +# message to print. +####################################### +function info() { + echo "::info::$*"; +} + +####################################### +# Executes commands defined within yml file or env variable +# Arguments: +# hook -> the hook to use +# +####################################3# +function cmd_from_yml() { + local FILE_NAME="templatesync.yml" + local HOOK=$1 + local YML_PATH_SUFF=".${HOOK}.commands" + + if [ "$IS_ALLOW_HOOKS" != "true" ]; then + debug "execute cmd hooks not enabled" + else + info "execute cmd hooks enabled" + + if ! [ -x "$(command -v yq)" ]; then + err "yaml query yq is not installed. 'https://mikefarah.gitbook.io/yq/'"; + exit 1; + fi + + if [[ -n "${HOOKS}" ]]; then + debug "hooks input variable is set. Using the variable" + echo "${HOOKS}" > "tmp.${FILE_NAME}" + YML_PATH="${YML_PATH_SUFF}" + else + cp ${FILE_NAME} "tmp.${FILE_NAME}" + YML_PATH=".hooks${YML_PATH_SUFF}" + fi + + readarray cmd_Arr < <(yq "${YML_PATH} | .[]" "tmp.${FILE_NAME}") + + rm "tmp.${FILE_NAME}" + + for key in "${cmd_Arr[@]}"; do echo "${key}" | bash; done + fi +} diff --git a/third_party/AndreasAugustin/actions-template-sync/src/sync_template.sh b/third_party/AndreasAugustin/actions-template-sync/src/sync_template.sh new file mode 100644 index 00000000..908348b6 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/src/sync_template.sh @@ -0,0 +1,607 @@ +#!/usr/bin/env bash + +set -e +# set -u +# set -x + +SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" + +# shellcheck source=src/sync_template.sh +source "${SCRIPT_DIR}/sync_common.sh" + +############################################ +# Prechecks +############################################ + +if [[ -z "${PR_COMMIT_MSG}" ]]; then + err "Missing env variable 'PR_COMMIT_MSG'"; + exit 1; +fi + +if [[ -z "${SOURCE_REPO}" ]]; then + err "Missing env variable 'SOURCE_REPO'"; + exit 1; +fi + +if ! [ -x "$(command -v gh)" ]; then + err "github-cli gh is not installed. 'https://github.com/cli/cli'"; + exit 1; +fi + +if [[ -z "${TEMPLATE_SYNC_IGNORE_FILE_PATH}" ]]; then + err "Missing env variable 'TEMPLATE_SYNC_IGNORE_FILE_PATH'"; + exit 1; +fi + +if [[ -z "${GITHUB_SERVER_URL}" ]]; then + err "Missing env variable 'GITHUB_SERVER_URL' of the target github server. E.g. https://github.com" +fi + +info "prechecks passed" +######################################################## +# Variables +######################################################## + +if [[ -z "${UPSTREAM_BRANCH}" ]]; then + UPSTREAM_BRANCH="$(git remote show origin | awk '/HEAD branch/ {print $NF}')" + info "Missing env variable 'UPSTREAM_BRANCH' setting to remote default ${UPSTREAM_BRANCH}"; +fi + +if [[ -n "${SRC_SSH_PRIVATEKEY_ABS_PATH}" ]]; then + debug "using ssh private key for private source repository" + export GIT_SSH_COMMAND="ssh -i ${SRC_SSH_PRIVATEKEY_ABS_PATH}" +fi + +TEMPLATE_SYNC_IGNORE_FILE_PATH="${TEMPLATE_SYNC_IGNORE_FILE_PATH:-".templatesyncignore"}" +IS_WITH_TAGS="${IS_WITH_TAGS:-"false"}" +IS_FORCE_PUSH_PR="${IS_FORCE_PUSH_PR:-"false"}" +IS_KEEP_BRANCH_ON_PR_CLEANUP="${IS_KEEP_BRANCH_ON_PR_CLEANUP:-"false"}" +GIT_REMOTE_PULL_PARAMS="${GIT_REMOTE_PULL_PARAMS:---allow-unrelated-histories --squash --strategy=recursive -X theirs}" + +TEMPLATE_REMOTE_GIT_HASH=$(git ls-remote "${SOURCE_REPO}" HEAD | awk '{print $1}') +SHORT_TEMPLATE_GIT_HASH=$(git rev-parse --short "${TEMPLATE_REMOTE_GIT_HASH}") +LOCAL_CURRENT_GIT_HASH=$(git rev-parse HEAD) # need to be run before a pull to get the current local git hash + +info "current git hash: ${LOCAL_CURRENT_GIT_HASH}" + +export TEMPLATE_GIT_HASH=${SHORT_TEMPLATE_GIT_HASH} +export PR_BRANCH="${PR_BRANCH_NAME_PREFIX}_${TEMPLATE_GIT_HASH}" +: "${PR_BODY:="Merge ${SOURCE_REPO} ${TEMPLATE_GIT_HASH}"}" +: "${PR_TITLE:-"upstream merge template repository"}" + +# for some reasons the substitution is not working as expected +# so we substitute manually +# shellcheck disable=SC2016 +PR_BODY=${PR_BODY//'${TEMPLATE_GIT_HASH}'/"${TEMPLATE_GIT_HASH}"} +# shellcheck disable=SC2016 +PR_BODY=${PR_BODY//'${SOURCE_REPO}'/"${SOURCE_REPO}"} + +# shellcheck disable=SC2016 +PR_TITLE=${PR_TITLE//'${TEMPLATE_GIT_HASH}'/"${TEMPLATE_GIT_HASH}"} +# shellcheck disable=SC2016 +PR_TITLE=${PR_TITLE//'${SOURCE_REPO}'/"${SOURCE_REPO}"} + +debug "TEMPLATE_GIT_HASH ${TEMPLATE_GIT_HASH}" +debug "PR_BRANCH ${PR_BRANCH}" +debug "PR_BODY ${PR_BODY}" + +# Check if the Ignore File exists inside .github folder or if it doesn't exist at all +if [[ -f ".github/${TEMPLATE_SYNC_IGNORE_FILE_PATH}" || ! -f "${TEMPLATE_SYNC_IGNORE_FILE_PATH}" ]]; then + debug "using ignore file as in .github folder" + TEMPLATE_SYNC_IGNORE_FILE_PATH=".github/${TEMPLATE_SYNC_IGNORE_FILE_PATH}" +fi + +info "variables done" + +##################################################### +# Functions +##################################################### + +####################################### +# doing the login to the source repository using gh cli +# Arguments: +# github_server url +####################################### +function gh_login_target_github() { + echo "::group::login target github" + local github_server_url=$1 + + if [[ -n "${TARGET_GH_TOKEN}" ]]; then + target_repo_hostname=$(echo "${github_server_url}" | cut -d '/' -f 3) + info "target server url: ${target_repo_hostname}" + info "logging out of the target if logged in" + gh auth logout --hostname "${target_repo_hostname}" || debug "not logged in" + # unset GITHUB_TOKEN + info "login to the target git repository" + gh auth login --git-protocol "https" --hostname "${target_repo_hostname}" --with-token <<< "${TARGET_GH_TOKEN}" || warn "login with target token somehow did not work. Please consider using the \'target_github_token\` parameter." + gh auth setup-git --hostname "${target_repo_hostname}" + gh auth status --hostname "${target_repo_hostname}" + fi + + echo "::endgroup::" +} + +####################################### +# set the gh action outputs if run with github action. +# Arguments: +# pr_branch +# template_git_hash +####################################### +function set_github_action_outputs() { + echo "::group::set gh action outputs" + + local pr_branch=$1 + local template_git_hash=$2 + + info "set github action outputs" + + if [[ -z "${GITHUB_RUN_ID}" ]]; then + info "env var 'GITHUB_RUN_ID' is empty -> no github action workflow" + else + # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter + echo "pr_branch=${pr_branch}" >> "$GITHUB_OUTPUT" + echo "template_git_hash=${template_git_hash}" >> "$GITHUB_OUTPUT" + fi + echo "::endgroup::" +} + +####################################### +# Check if the branch exists remote. +# Arguments: +# pr_branch +####################################### +function check_branch_remote_existing() { + + local branch_to_check=$1 + + info "check if the remote branch ${branch_to_check} exists. Exit if so" + + git ls-remote --exit-code --heads origin "${branch_to_check}" || branch_does_not_exist=true + + if [[ "${branch_does_not_exist}" != true ]]; then + warn "Git branch '${branch_to_check}' exists in the remote repository" + set_github_action_outputs "${branch_to_check}" + exit 0 + fi +} + +####################################### +# Check if the commit is already in history. +# exit 0 if so +# Arguments: +# template_remote_git_hash +####################################### +function check_if_commit_already_in_hist_graceful_exit() { + info "check if commit already in history" + + local template_remote_git_hash=$1 + + git cat-file -e "${template_remote_git_hash}" || commit_not_in_hist=true + if [ "${commit_not_in_hist}" != true ] ; then + warn "repository is up to date!" + exit 0 + fi +} + +########################################## +# check if there are staged files. +# exit if not +########################################## +function check_staged_files_available_graceful_exit() { + if git diff --quiet && git diff --staged --quiet; then + info "nothing to commit" + exit 0 + fi +} + +####################################### +# force source file deletion if they had been deleted +# Arguments: +# local_current_git_hash +####################################### +function force_delete_files() { + info "force delete files" + warn "force file deletion is enabled. Deleting files which are deleted within the target repository" + local local_current_git_hash=$1 + + info "current git hash: ${local_current_git_hash}" + + files_to_delete=$(git log --diff-filter D --pretty="format:" --name-only "${local_current_git_hash}"..HEAD | sed '/^$/d') + warn "files to delete: ${files_to_delete}" + if [[ -n "${files_to_delete}" ]]; then + echo "${files_to_delete}" | xargs rm + fi +} + +####################################### +# cleanup older prs based on labels. +# Arguments: +# upstream_branch +# pr_labels +# is_keep_branch_on_pr_cleanup +# local_branch_name +####################################### +function cleanup_older_prs () { + info "cleanup older prs" + + local upstream_branch=$1 + local pr_labels=$2 + local is_keep_branch_on_pr_cleanup=$3 + local local_branch_name=$4 + + if [[ -z "${pr_labels}" ]]; then + warn "env var 'PR_LABELS' is empty. Skipping older prs cleanup" + return 0 + fi + + older_prs=$(gh pr list \ + --base "${upstream_branch}" \ + --state open \ + --label "${pr_labels}" \ + --json number,headRefName \ + --jq '.[]') + + for older_pr in $older_prs + do + branch_name=$(echo "$older_pr" | jq -r .headRefName) + pr_number=$(echo "$older_pr" | jq -r .number) + + if [ "$branch_name" == "$local_branch_name" ] ; then + warn "local branch name equals remote pr branch name ${local_branch_name}. Skipping pr cleanup for this branch" + continue + fi + + if [ "$is_keep_branch_on_pr_cleanup" == true ] ; then + gh pr close -c "[actions-template-sync] :construction_worker: automatically closed because there is a new open PR. Branch is kept alive" "$pr_number" + debug "Closed PR #${older_pr} but kept the branch" + else + gh pr close -c "[actions-template-sync] :construction_worker: automatically closed because there is a new open PR" -d "$pr_number" + debug "Closed PR #${older_pr}" + fi + done +} + +################################## +# pull source changes +# Arguments: +# source_repo +# git_remote_pull_params +################################## +function pull_source_changes() { + info "pull changes from source repository" + local source_repo=$1 + local git_remote_pull_params=$2 + + eval "git pull ${source_repo} --tags ${git_remote_pull_params}" || pull_has_issues=true + + info "finished pulling from the source." + info "logging out from source ${SOURCE_REPO_HOSTNAME}." + + if [ "$pull_has_issues" == true ] ; then + warn "There had been some git pull issues." + warn "Maybe a merge issue." + warn "We go on but it is likely that you need to fix merge issues within the created PR." + fi + + gh_login_target_github "${GITHUB_SERVER_URL}" +} + +####################################### +# eventual create labels (if they are not existent). +# Arguments: +# pr_labels +####################################### +function eventual_create_labels () { + local pr_labels=$1 + info "eventual create labels ${pr_labels}" + + if [[ -z "${pr_labels}" ]]; then + info "'pr_labels' is empty. Skipping labels check" + retun 0 + fi + + readarray -t labels_array < <(awk -F',' '{ for( i=1; i<=NF; i++ ) print $i }' <<<"${pr_labels}") + for label in "${labels_array[@]}" + do + search_result=$(gh label list \ + --search "${label}" \ + --limit 1 \ + --json name \ + --template '{{range .}}{{printf "%v" .name}}{{"\n"}}{{end}}') + + if [ "${search_result}" = "${label##[[:space:]]}" ]; then + info "label '${label##[[:space:]]}' was found in the repository" + else + if gh label create "${label}"; then + info "label '${label}' was missing and has been created" + else + warn "label creation did not work. For any reason the former check sometimes is failing" + fi + fi + done +} + +############################## +# push the changes +# Arguments: +# branch +# is_force +# is_with_tags +############################## +function push () { + info "push changes" + + + local branch=$1 + local is_force=$2 + local is_with_tags=$3 + + args=(--set-upstream origin "${branch}") + + if [ "$is_force" == true ] ; then + warn "forcing the push." + args+=(--force) + fi + + if [ "$is_with_tags" == true ] ; then + warn "include tags." + args+=(--tags) + fi + + git push "${args[@]}" + +} + +#################################### +# creates a pr +# Arguments: +# title +# body +# branch +# labels +# reviewers +################################### +function create_pr() { + info "create pr" + local title=$1 + local body=$2 + local branch=$3 + local labels=$4 + local reviewers=$5 + + gh pr create \ + --title "${title}" \ + --body "${body}" \ + --base "${branch}" \ + --label "${labels}" \ + --reviewer "${reviewers}" || create_pr_has_issues=true + + if [ "$create_pr_has_issues" == true ] ; then + warn "Creating the PR failed." + warn "Eventually it is already existent." + return 1 + fi + return 0 +} + +#################################### +# creates or edits a pr if already existent +# Arguments: +# title +# body +# upstream_branch +# labels +# reviewers +################################### +function create_or_edit_pr() { + info "create pr or edit the pr" + local title=$1 + local body=$2 + local upstream_branch=$3 + local labels=$4 + local reviewers=$5 + local pr_branch=$6 + + create_pr "${title}" "${body}" "${upstream_branch}" "${labels}" "${reviewers}" || gh pr edit \ + --title "${title}" \ + --body "${body}" \ + --add-label "${labels}" \ + --add-reviewer "${reviewers}" +} + +######################################### +# restore the .templatesyncignore file +# Arguments: +# template_sync_ignore_file_path +########################################### +function restore_templatesyncignore_file() { + info "restore the ignore file" + local template_sync_ignore_file_path=$1 + if [ -s "${template_sync_ignore_file_path}" ]; then + git reset "${template_sync_ignore_file_path}" + git checkout -- "${template_sync_ignore_file_path}" || warn "not able to checkout the former .templatesyncignore file. Most likely the file was not present" + fi +} + +######################################### +# reset all files within the .templatesyncignore file +# Arguments: +# template_sync_ignore_file_path +########################################### +function handle_templatesyncignore() { + info "handle .templatesyncignore" + local template_sync_ignore_file_path=$1 + # we are checking the ignore file if it exists or is empty + # -s is true if the file contains whitespaces + if [ -s "${template_sync_ignore_file_path}" ]; then + debug "unstage files from template sync ignore ${template_sync_ignore_file_path}" + tr -d '\r' < "${template_sync_ignore_file_path}" | sed '/^[[:blank:]]*#/d;s/#.*//' | awk NF | xargs -r git reset -- + + debug "clean untracked files" + git clean -df + + debug "discard all unstaged changes" + git checkout -- . + fi +} + +######################################################## +# Logic +####################################################### + +function arr_prechecks() { + info "prechecks" + echo "::group::prechecks" + if [ "${IS_FORCE_PUSH_PR}" == "true" ]; then + warn "skipping prechecks because we force push and pr" + return 0 + fi + check_branch_remote_existing "${PR_BRANCH}" + + check_if_commit_already_in_hist_graceful_exit "${TEMPLATE_REMOTE_GIT_HASH}" + + echo "::endgroup::" +} + + +function arr_checkout_branch_and_pull() { + info "checkout branch and pull" + cmd_from_yml "prepull" + + echo "::group::checkout branch and pull" + + debug "create new branch from default branch with name ${PR_BRANCH}" + git checkout -b "${PR_BRANCH}" + debug "pull changes from template" + + pull_source_changes "${SOURCE_REPO}" "${GIT_REMOTE_PULL_PARAMS}" + + restore_templatesyncignore_file "${TEMPLATE_SYNC_IGNORE_FILE_PATH}" + + if [ "$IS_FORCE_DELETION" == "true" ]; then + force_delete_files "${LOCAL_CURRENT_GIT_HASH}" + fi + + echo "::endgroup::" +} + + +function arr_commit() { + info "commit" + + cmd_from_yml "precommit" + + echo "::group::commit changes" + + git add . + + handle_templatesyncignore "${TEMPLATE_SYNC_IGNORE_FILE_PATH}" + + check_staged_files_available_graceful_exit + + git commit --signoff -m "${PR_COMMIT_MSG}" + + echo "::endgroup::" +} + + +function arr_push() { + info "push" + + echo "::group::push" + if [ "$IS_DRY_RUN" == "true" ]; then + warn "dry_run option is set to on. skipping push" + return 0 + fi + cmd_from_yml "prepush" + push "${PR_BRANCH}" "${IS_FORCE_PUSH_PR}" "${IS_WITH_TAGS}" + echo "::endgroup::" +} + +function arr_prepare_pr_create_pr() { + info "prepare_pr_create_pr" + if [ "$IS_DRY_RUN" == "true" ]; then + warn "dry_run option is set to on. skipping labels check, cleanup older PRs, push and create pr" + return 0 + fi + echo "::group::check for missing labels" + + eventual_create_labels "${PR_LABELS}" + + echo "::endgroup::" + + echo "::group::cleanup older PRs" + if [ "$IS_PR_CLEANUP" != "false" ]; then + if [[ -z "${PR_LABELS}" ]]; then + warn "env var 'PR_LABELS' is empty. Skipping older prs cleanup" + else + cmd_from_yml "precleanup" + cleanup_older_prs "${UPSTREAM_BRANCH}" "${PR_LABELS}" "${IS_KEEP_BRANCH_ON_PR_CLEANUP}" "${PR_BRANCH}" + fi + else + warn "is_pr_cleanup option is set to off. Skipping older prs cleanup" + fi + + echo "::endgroup::" + + echo "::group::create PR" + + cmd_from_yml "prepr" + if [ "$IS_FORCE_PUSH_PR" == true ] ; then + create_or_edit_pr "${PR_TITLE}" "${PR_BODY}" "${UPSTREAM_BRANCH}" "${PR_LABELS}" "${PR_REVIEWERS}" + else + create_pr "${PR_TITLE}" "${PR_BODY}" "${UPSTREAM_BRANCH}" "${PR_LABELS}" "${PR_REVIEWERS}" + fi + + + echo "::endgroup::" +} + +declare -A cmd_arr +declare -a orders; + +cmd_arr["prechecks"]=arr_prechecks; orders+=("prechecks") +cmd_arr["pull"]=arr_checkout_branch_and_pull; orders+=("pull") +cmd_arr["commit"]=arr_commit; orders+=("commit") +cmd_arr["push"]=arr_push; orders+=("push") +cmd_arr["pr"]=arr_prepare_pr_create_pr; orders+=("pr") + +if [[ -z "${STEPS}" ]]; then + info "no steps provided. Default is to execute all." + for key in "${orders[@]}"; + do + debug "execute cmd ${key}" + ${cmd_arr[${key}]} + done +else + info "steps provided." + readarray -t steps < <(awk -F',' '{ for( i=1; i<=NF; i++ ) print $i }' <<<"${STEPS}") + # check if steps are supported + not_supported_steps="" + for step in "${steps[@]}"; + do + matched=false + for key in "${orders[@]}"; + do + debug "execute cmd ${key}" + if [[ "${step}" == "${key}" ]]; then + matched=true; + fi + done + if [[ "$matched" == 'false' ]]; then + not_supported_steps="${not_supported_steps} $step" + fi + done + if [[ -z "${not_supported_steps}" ]]; then + for step in "${steps[@]}"; + do + debug "execute cmd ${step}" + ${cmd_arr[${step}]} + done + else + err "following steps are not supported ${not_supported_steps}" + exit 1 + fi +fi + +set_github_action_outputs "${PR_BRANCH}" "${TEMPLATE_GIT_HASH}" diff --git a/third_party/AndreasAugustin/actions-template-sync/templatesync.yml b/third_party/AndreasAugustin/actions-template-sync/templatesync.yml new file mode 100644 index 00000000..da280480 --- /dev/null +++ b/third_party/AndreasAugustin/actions-template-sync/templatesync.yml @@ -0,0 +1,11 @@ +# validate + +hooks: + prepull: + commands: + - echo "foo ${MY_VAR}" + - echo 'hi, we are within the prepull phase' + prepush: + commands: + - echo 'hi, we are within the prepush phase' + - echo 'maybe you want to add further changes and commits' diff --git a/tools/third_party_sync/repos.lock.json b/tools/third_party_sync/repos.lock.json index 25979bfb..38019b0e 100644 --- a/tools/third_party_sync/repos.lock.json +++ b/tools/third_party_sync/repos.lock.json @@ -1,3 +1,11 @@ { - "repositories": {} + "repositories": { + "actions-template-sync": { + "published_at": "2025-07-16T19:52:05Z", + "resolved_commit": "8ec19a5f2721ffb81ff809aa340ddf75e6a85ea6", + "resolved_release": "v2.5.2", + "source": "release", + "tarball_url": "https://api.github.com/repos/AndreasAugustin/actions-template-sync/tarball/v2.5.2" + } + } }