├── .gitignore ├── logo.png ├── avatars └── Norbert Bartko.png ├── .editorconfig ├── .github ├── workflows │ ├── label-syncer.yml │ ├── gource.yml │ └── gource-dev.yml └── labels.yml ├── LICENSE ├── Dockerfile ├── action.yml ├── gource.sh ├── entrypoint.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /logs 2 | /test 3 | **/*.mp4 4 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NBprojekt/gource-action/HEAD/logo.png -------------------------------------------------------------------------------- /avatars/Norbert Bartko.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NBprojekt/gource-action/HEAD/avatars/Norbert Bartko.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.yml] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.github/workflows/label-syncer.yml: -------------------------------------------------------------------------------- 1 | name: Sync labels 2 | on: 3 | push: 4 | branches: 5 | - master 6 | paths: 7 | - .github/labels.yml 8 | jobs: 9 | sync-labels: 10 | name: 'Sync labels' 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | - name: Label Syncer 17 | uses: micnncim/action-label-syncer@v0.3.1 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 20 | GITHUB_REPOSITORY: ${{ github.repository }} 21 | with: 22 | manifest: .github/labels.yml 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Norbert Bartko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM utensils/opengl:stable 2 | 3 | # Install all needed runtime dependencies. 4 | RUN \ 5 | set -xe; \ 6 | apk --update add --no-cache --virtual .runtime-deps \ 7 | bash \ 8 | ffmpeg \ 9 | git \ 10 | gource \ 11 | imagemagick \ 12 | jq; 13 | 14 | # Copy scripts into image 15 | COPY ./entrypoint.sh ./gource.sh /usr/local/bin/ 16 | 17 | # Add executable right to scripts 18 | RUN \ 19 | chmod +x /usr/local/bin/entrypoint.sh; \ 20 | chmod +x /usr/local/bin/gource.sh; 21 | 22 | # Create working directories 23 | RUN \ 24 | mkdir /gource; \ 25 | mkdir /gource/logs; \ 26 | mkdir /gource/avatars; \ 27 | mkdir /gource/git_repo; \ 28 | mkdir /gource/git_repos; \ 29 | mkdir /gource/output; 30 | 31 | # Set working directory with full access 32 | WORKDIR /gource 33 | RUN chmod -R 777 /gource 34 | 35 | # Set environment variables 36 | ENV \ 37 | DISPLAY=":99" \ 38 | GLOBAL_FILTERS="" \ 39 | GOURCE_FILTERS="" \ 40 | GOURCE_USER_IMAGE_DIR="/gource/avatars" \ 41 | H264_CRF="23" \ 42 | H264_LEVEL="5.1" \ 43 | H264_PRESET="medium" \ 44 | INVERT_COLORS="false" \ 45 | XVFB_WHD="3840x2160x24" 46 | 47 | # Set our entrypoint. 48 | ENTRYPOINT ["bash", "/usr/local/bin/entrypoint.sh"] 49 | -------------------------------------------------------------------------------- /.github/workflows/gource.yml: -------------------------------------------------------------------------------- 1 | name: Gource Action Build 2 | on: 3 | release: 4 | types: 5 | - published 6 | 7 | jobs: 8 | gource-action: 9 | name: 'Local visualisation' 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: 'Checkout' 14 | uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: 'Gource Action' 19 | uses: nbprojekt/gource-action@master 20 | with: 21 | git_url: ./ 22 | avatars_url: ./avatars/ 23 | gource_title: 'Gource action' 24 | logo_url: 'https://user-images.githubusercontent.com/24683383/92398226-79a40680-f128-11ea-9f54-6ccbaca4a6a5.png' 25 | 26 | - name: 'Upload gource video' 27 | uses: actions/upload-artifact@v4 28 | with: 29 | name: Gource action 30 | path: ./gource/gource.mp4 31 | 32 | gource-docker-cli: 33 | name: 'Docker CLI visualisation' 34 | runs-on: ubuntu-latest 35 | 36 | steps: 37 | - name: 'Gource Action' 38 | uses: nbprojekt/gource-action@master 39 | with: 40 | git_url: https://github.com/docker/cli 41 | gource_title: 'Docker CLI' 42 | logo_url: 'https://user-images.githubusercontent.com/24683383/92395924-70189f80-f124-11ea-815c-aa4d9f4de29d.png' 43 | gource_resolution: '1080p' 44 | gource_fps: 60 45 | gource_font_size: 40 46 | gource_start_date: '2016-04-18' 47 | gource_stop_date: '2019-12-31' 48 | 49 | - name: 'Upload gource video' 50 | uses: actions/upload-artifact@v4 51 | with: 52 | name: Docker CLI 53 | path: ./gource/gource.mp4 54 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - name: Blocked 4 | description: Blocked by another issue we need to address first. 5 | color: d73a4a 6 | - name: Bot 7 | description: A bot interacted with this issue or pull request 8 | color: 6f57db 9 | - name: Bug 10 | description: Something isn't working 11 | color: d73a4a 12 | - name: CI / CD 13 | description: Related to continuous integration and delivery 14 | color: 0366d6 15 | - name: Dependencies 16 | description: Pull requests that update a dependency file 17 | color: 0366d6 18 | - name: Documentation 19 | description: Improvements or additions to documentation 20 | color: 0366d6 21 | - name: Feature Request 22 | description: Request to add a new feature 23 | color: 008672 24 | - name: Feature 25 | description: New feature that will be added to the project 26 | color: cc227a 27 | - name: Fix 28 | description: Pull requests that fixed a bug 29 | color: cc227a 30 | - name: Good first issue 31 | description: Good for newcomers 32 | color: 7057ff 33 | - name: Help wanted 34 | description: This issue is available to anyone that wants to help 35 | color: 008672 36 | # - name: 'Needs: Design' 37 | # description: The issues needs design work before implementing 38 | # color: c513d6 39 | # - name: 'Needs: Feedback' 40 | # description: The issues needs feedback before implementing 41 | # color: c513d6 42 | # - name: 'Needs: Investigation' 43 | # description: The issues needs investigation before implementing 44 | # color: c513d6 45 | # - name: 'Needs: More Information' 46 | # description: The author needs to provide more information on the issue. 47 | # color: c513d6 48 | - name: 'P1' 49 | description: Bug or feature that has to be be fixed in the next patch 50 | color: 0D47A1 51 | - name: 'P2' 52 | description: Bug or feature that has to be be fixed in the next minor patch 53 | color: 1976D2 54 | - name: 'P3' 55 | description: Bug or feature that has to be be fixed in the next major patch 56 | color: 42A5F5 57 | - name: 'P4' 58 | description: 59 | color: 8DC9F9 60 | - name: 'P5' 61 | description: 62 | color: C5DEF5 63 | - name: 'Question' 64 | description: Question about this project 65 | color: 7057ff 66 | # - name: 'Resolved: Answered' 67 | # description: The question raised by the author has been answered 68 | # color: 651ace 69 | # - name: 'Resolved: By Design' 70 | # description: Resolved as behaviour is by design 71 | # color: 651ace 72 | # - name: 'Resolved: Completed' 73 | # description: The issue has been resolved 74 | # color: 651ace 75 | # - name: 'Resolved: Duplicate' 76 | # description: This issue or pull request already exists 77 | # color: 651ace 78 | # - name: 'Resolved: Won't Fix' 79 | # description: The reported behaviour will not be changed 80 | # color: 651ace 81 | - name: 'Triage' 82 | description: Issue needs to be triaged 83 | color: 7057ff 84 | -------------------------------------------------------------------------------- /.github/workflows/gource-dev.yml: -------------------------------------------------------------------------------- 1 | name: Gource Action Dev 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | logLevel: 6 | description: 'Log level' 7 | required: true 8 | default: 'warning' 9 | type: choice 10 | options: 11 | - info 12 | - warning 13 | - debug 14 | push: 15 | branches: 16 | - master 17 | - 'dev/**' 18 | 19 | jobs: 20 | # local-images: 21 | # runs-on: ubuntu-latest 22 | 23 | # steps: 24 | # - name: 'Checkout' 25 | # uses: actions/checkout@v4 26 | # with: 27 | # fetch-depth: 0 28 | 29 | # - name: 'Current folder' 30 | # run: ls -al 31 | 32 | # - name: 'Gource Action' 33 | # uses: ./ 34 | # with: 35 | # git_url: ./ 36 | # avatars_url: ./avatars/ 37 | # gource_title: 'Gource Action Development' 38 | # logo_url: ./logo.png 39 | # avatars_auto_fetch: true 40 | 41 | # - name: 'Check output' 42 | # run: | 43 | # ls -al ./ 44 | # ls -al ./gource 45 | 46 | # - uses: actions/upload-artifact@v4 47 | # with: 48 | # name: gource-local 49 | # path: ./gource 50 | # retention-days: 1 51 | 52 | # test-new-url-regex: 53 | # runs-on: ubuntu-latest 54 | 55 | # steps: 56 | # - name: 'Checkout' 57 | # uses: actions/checkout@v4 58 | # with: 59 | # fetch-depth: 0 60 | 61 | # - name: 'Current folder' 62 | # run: ls -al 63 | 64 | # - name: 'Gource Action' 65 | # uses: ./ 66 | # with: 67 | # git_url: ./ 68 | # avatars_url: ./avatars/ 69 | # gource_title: 'Gource Action Development' 70 | # logo_url: https://raw.githubusercontent.com/glotaran/pyglotaran/main/docs/source/images/glotaran.png?raw=true 71 | # avatars_auto_fetch: true 72 | 73 | # - name: 'Check output' 74 | # run: | 75 | # ls -al ./ 76 | # ls -al ./gource 77 | 78 | # - uses: actions/upload-artifact@v4 79 | # with: 80 | # name: gource-local 81 | # path: ./gource 82 | # retention-days: 1 83 | 84 | check-new-options: 85 | runs-on: ubuntu-latest 86 | 87 | steps: 88 | - name: 'Checkout' 89 | uses: actions/checkout@v4 90 | with: 91 | fetch-depth: 0 92 | 93 | - name: 'Gource Action' 94 | uses: ./ 95 | with: 96 | git_url: https://github.com/chkpwd/dotfiles 97 | gource_title: IaC Repo 98 | logo_url: https://github.com/git.png 99 | gource_resolution: 1080p 100 | gource_fps: 60 101 | avatars_auto_fetch: true 102 | gource_bloom_intensity: 0.5 103 | gource_bloom_multiplier: 0.5 104 | gource_auto_skip_seconds: 0.1 105 | gource_camera_mode: track 106 | gource_filename_time: 2 107 | gource_seconds_per_day: 0.25 108 | gource_time_scale: 2.5 109 | gource_background_color: 0D1116 110 | gource_overlay_background_color: 0D1116 111 | gource_font_size: 80 112 | gource_hide_items: mouse,progress,dirnames 113 | 114 | 115 | - name: 'Upload gource video' 116 | uses: actions/upload-artifact@v4 117 | with: 118 | name: Gource 119 | path: ./gource/gource.mp4 120 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'Gource-Action' 2 | description: 'Visualisation action for source control repositories using gource.' 3 | author: 'Norbert Bartko' 4 | 5 | inputs: 6 | git_url: 7 | description: 'Location of git repository. Can also be an remote repository e.g.: https://github.com/acaudwell/Gource.git' 8 | default: './' 9 | required: false 10 | git_token: 11 | description: 'If the provided repository is private, the action need an token with read scope.' 12 | default: '' 13 | required: false 14 | logo_url: 15 | description: 'Displayed icon on bottom right corner.' 16 | default: '' 17 | required: false 18 | avatars_auto_fetch: 19 | description: 'Tries to fetch user avatar from all contributors. If this is enable "avatars_url" will be ignored.' 20 | default: 'false' 21 | required: false 22 | avatars_url: 23 | description: 'Path of local directory containing user avatars.' 24 | default: '' 25 | required: false 26 | gource_title: 27 | description: 'Set a title.' 28 | default: 'Title' 29 | required: false 30 | gource_resolution: 31 | description: 'Used gource resolution (2160p, 1440p, 1080p, 720p).' 32 | default: '1080p' 33 | required: false 34 | gource_fps: 35 | description: 'Used gource fps.' 36 | default: '60' 37 | required: false 38 | gource_bloom_multiplier: 39 | description: 'Adjust the amount of bloom.' 40 | default: '0.5' 41 | required: false 42 | gource_bloom_intensity: 43 | description: 'Adjust the intensity of bloom.' 44 | default: '0.5' 45 | required: false 46 | gource_key: 47 | description: 'Show file extension key.' 48 | default: '' 49 | required: false 50 | gource_auto_skip_seconds: 51 | description: 'Skip to next entry if nothing happens for a number of seconds.' 52 | default: '0.5' 53 | required: false 54 | gource_background_color: 55 | description: 'Background colour in hex.' 56 | default: '0a0a0a' 57 | required: false 58 | gource_overlay_background_color: 59 | description: 'Overlay background colour in hex.' 60 | default: '202021' 61 | required: false 62 | gource_font_color: 63 | description: 'Font color used by the date and title in hex.' 64 | default: 'F0F0F0' 65 | required: false 66 | gource_overlay_font_color: 67 | description: 'Font color used by the overlay in hex.' 68 | default: 'F0F0F0' 69 | required: false 70 | gource_font_size: 71 | description: 'Font size used by the date and title.' 72 | default: '44' 73 | required: false 74 | gource_camera_mode: 75 | description: 'Camera mode (overview, track).' 76 | default: 'overview' 77 | required: false 78 | gource_dir_depth: 79 | description: 'Draw names of directories down to a specific depth in the tree.' 80 | default: '3' 81 | required: false 82 | gource_filename_time: 83 | description: 'Duration to keep filenames on screen (>= 2.0).' 84 | default: '2' 85 | required: false 86 | gource_hide_items: 87 | description: 'Hide one or more display elements from the list below.' 88 | default: 'mouse,date,filenames' 89 | required: false 90 | gource_max_user_speed: 91 | description: 'Max speed users can travel per second.' 92 | default: '500' 93 | required: false 94 | gource_seconds_per_day: 95 | description: 'Speed of simulation in seconds per day.' 96 | default: '0.1' 97 | required: false 98 | gource_time_scale: 99 | description: 'Change simulation time scale.' 100 | default: '1.5' 101 | required: false 102 | gource_user_scale: 103 | description: 'Change scale of user avatars.' 104 | default: '1.2' 105 | required: false 106 | gource_start_date: 107 | description: 'Start with the first entry after the supplied date and optional time.' 108 | default: '' 109 | required: false 110 | gource_stop_date: 111 | description: 'Stop after the last entry prior to the supplied date and optional time.' 112 | default: '' 113 | required: false 114 | gource_file_filter: 115 | description: 'Filter out file paths matching the specified regular expression.' 116 | default: '' 117 | required: false 118 | 119 | runs: 120 | using: 'docker' 121 | image: 'Dockerfile' 122 | 123 | branding: 124 | icon: 'monitor' 125 | color: 'purple' 126 | -------------------------------------------------------------------------------- /gource.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | printf "> \tSetup\n" 4 | # Predefined resolutions and settings. 5 | if [[ "${INPUT_GOURCE_RESOLUTION}" == "2160p" ]]; then 6 | GOURCE_RES="3500x1940" 7 | OVERLAY_RES="1920x1080" 8 | GOURCE_PAD="3520:1960:3520:1960:#313133" 9 | KEY_CROP="320:1860:0:0" 10 | KEY_PAD="320:1960:0:0:#202021" 11 | DATE_CROP="3520:200:640:0" 12 | DATE_PAD="3840:200:320:200:#202021" 13 | OUTPUT_RES="3840:2160" 14 | printf "> \t\tUsing 2160p settings. Output will be 3840x2160 at ${INPUT_GOURCE_FPS}fps.\n" 15 | elif [[ "${INPUT_GOURCE_RESOLUTION}" == "1440p" ]]; then 16 | GOURCE_RES="2333x1293" 17 | OVERLAY_RES="1920x1080" 18 | GOURCE_PAD="2346:1306:2346:1306:#313133" 19 | KEY_CROP="214:1240:0:0" 20 | KEY_PAD="214:1306:0:0:#202021" 21 | DATE_CROP="2346:134:426:0" 22 | DATE_PAD="2560:134:214:134:#202021" 23 | OUTPUT_RES="2560:1440" 24 | printf "> \t\tUsing 1440p settings. Output will be 2560x1440 at ${INPUT_GOURCE_FPS}fps.\n" 25 | elif [[ "${INPUT_GOURCE_RESOLUTION}" == "1080p" ]]; then 26 | GOURCE_RES="1750x970" 27 | OVERLAY_RES="1920x1080" 28 | GOURCE_PAD="1760:980:1760:980:#313133" 29 | KEY_CROP="160:930:0:0" 30 | KEY_PAD="160:980:0:0:#202021" 31 | DATE_CROP="1760:100:320:0" 32 | DATE_PAD="1920:100:160:100:#202021" 33 | OUTPUT_RES="1920:1080" 34 | printf "> \t\tUsing 1080p settings. Output will be 1920x1080 at ${INPUT_GOURCE_FPS}fps.\n" 35 | elif [[ "${INPUT_GOURCE_RESOLUTION}" == "720p" ]]; then 36 | GOURCE_RES="1116x646" 37 | OVERLAY_RES="1920x1080" 38 | GOURCE_PAD="1128:653:1128:653:#313133" 39 | KEY_CROP="102:590:0:0" 40 | KEY_PAD="102:590:0:0:#202021,scale=152:653" 41 | DATE_CROP="1128:67:152:0" 42 | DATE_PAD="1280:67:152:0:#202021" 43 | OUTPUT_RES="1280:720" 44 | printf "> \t\tUsing 720p settings. Output will be 1280x720 at ${INPUT_GOURCE_FPS}fps.\n" 45 | fi 46 | 47 | if [[ "${INVERT_COLORS}" == "true" ]]; then 48 | printf "> \t\tUsing inverted colors " 49 | GOURCE_FILTERS="${GOURCE_FILTERS},lutrgb=r=negval:g=negval:b=negval" 50 | else 51 | printf "> \t\tNot using inverted colors " 52 | fi 53 | 54 | printf "\n> \t\tCreate temp directory" 55 | mkdir ./tmp 56 | 57 | printf "\n> \t\tCreate gource pipe" 58 | mkfifo ./tmp/gource.pipe 59 | printf "\n> \t\tCreate overlay pipe" 60 | mkfifo ./tmp/overlay.pipe 61 | 62 | # Handle optional params whitch are not allowed to be empty 63 | OPTIONAL_PARAMS="" 64 | if [[ $INPUT_GOURCE_STOP_DATE == *[!\ ]* ]]; then # Temporyry fix, check if it's a date 65 | OPTIONAL_PARAMS+="--stop-date ${INPUT_GOURCE_STOP_DATE} " 66 | fi 67 | if [[ $INPUT_GOURCE_START_DATE == *[!\ ]* ]]; then # Temporyry fix, check if it's a date 68 | OPTIONAL_PARAMS+="--start-date ${INPUT_GOURCE_START_DATE} " 69 | fi 70 | if [[ ! -z "$INPUT_GOURCE_FILE_FILTER" ]]; then 71 | OPTIONAL_PARAMS+="--file-filter \"$INPUT_GOURCE_FILE_FILTER\" " 72 | fi 73 | 74 | printf "\n> \t\tUsing optional params: ${OPTIONAL_PARAMS}" 75 | 76 | printf "\n> \tGource" 77 | printf "\n> \t\tStarting Gource pipe for git repo" 78 | gource --seconds-per-day ${INPUT_GOURCE_SECONDS_PER_DAY} \ 79 | --user-scale ${INPUT_GOURCE_USER_SCALE} \ 80 | --time-scale ${INPUT_GOURCE_TIME_SCALE} \ 81 | --auto-skip-seconds ${INPUT_GOURCE_AUTO_SKIP_SECONDS} \ 82 | --title "${INPUT_GOURCE_TITLE}" \ 83 | --background-colour ${INPUT_GOURCE_BACKGROUND_COLOR} \ 84 | --font-colour ${INPUT_GOURCE_FONT_COLOR} \ 85 | --user-image-dir ${GOURCE_USER_IMAGE_DIR} \ 86 | --camera-mode ${INPUT_GOURCE_CAMERA_MODE} \ 87 | --hide ${INPUT_GOURCE_HIDE_ITEMS} \ 88 | --font-size ${INPUT_GOURCE_FONT_SIZE} \ 89 | --dir-name-depth ${INPUT_GOURCE_DIR_DEPTH} \ 90 | --filename-time ${INPUT_GOURCE_FILENAME_TIME} \ 91 | --max-user-speed ${INPUT_GOURCE_MAX_USER_SPEED} \ 92 | --bloom-multiplier ${INPUT_GOURCE_BLOOM_MULTIPLIER} \ 93 | --bloom-intensity ${INPUT_GOURCE_BLOOM_INTENSITY} \ 94 | --${GOURCE_RES} ${OPTIONAL_PARAMS} \ 95 | --stop-at-end \ 96 | ./development.log \ 97 | -r ${INPUT_GOURCE_FPS} \ 98 | -o - >./tmp/gource.pipe & 99 | 100 | printf "\n> \t\tStarting Gource pipe for overlay components" 101 | gource ${INPUT_GOURCE_KEY} \ 102 | --seconds-per-day ${INPUT_GOURCE_SECONDS_PER_DAY} \ 103 | --user-scale ${INPUT_GOURCE_USER_SCALE} \ 104 | --time-scale ${INPUT_GOURCE_TIME_SCALE} \ 105 | --auto-skip-seconds ${INPUT_GOURCE_AUTO_SKIP_SECONDS} \ 106 | --transparent \ 107 | --background-colour 202021 \ 108 | --font-colour ${INPUT_GOURCE_OVERLAY_FONT_COLOR} \ 109 | --camera-mode overview \ 110 | --hide bloom,dirnames,files,filenames,mouse,root,tree,users,usernames \ 111 | --font-size 60 \ 112 | --${OVERLAY_RES} ${OPTIONAL_PARAMS} \ 113 | --stop-at-end \ 114 | --dir-name-depth 3 \ 115 | --filename-time 2 \ 116 | --max-user-speed 500 \ 117 | ./development.log \ 118 | -r ${INPUT_GOURCE_FPS} \ 119 | -o - >./tmp/overlay.pipe & 120 | 121 | printf "\n> \t\tStart ffmpeg to merge the two video outputs" 122 | ffmpeg -y -r ${INPUT_GOURCE_FPS} -f image2pipe -probesize 100M -i ./tmp/gource.pipe \ 123 | -y -r ${INPUT_GOURCE_FPS} -f image2pipe -probesize 100M -i ./tmp/overlay.pipe \ 124 | ${LOGO} \ 125 | -filter_complex "[0:v]pad=${GOURCE_PAD}${GOURCE_FILTERS}[center];\ 126 | [1:v]scale=${OUTPUT_RES}[key_scale];\ 127 | [1:v]scale=${OUTPUT_RES}[date_scale];\ 128 | [key_scale]crop=${KEY_CROP},pad=${KEY_PAD}[key];\ 129 | [date_scale]crop=${DATE_CROP},pad=${DATE_PAD}[date];\ 130 | [key][center]hstack[with_key];\ 131 | [date][with_key]vstack[with_date]${LOGO_FILTER_GRAPH}${GLOBAL_FILTERS}" ${FILTER_GRAPH_MAP} \ 132 | -vcodec libx264 -level ${H264_LEVEL} -pix_fmt yuv420p -crf ${H264_CRF} -preset ${H264_PRESET} \ 133 | -bf 0 ./output/gource.mp4 &> ./logs/gource.log 134 | 135 | filesize="$(du -sh ./output/gource.mp4 | cut -f 1)" 136 | printf "\n> \t\tShow file size: $filesize" 137 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Switch to working directory 4 | cd /gource 5 | 6 | # Start Xvfb 7 | printf "> Starting Xvfb " 8 | Xvfb :99 -ac -screen 0 $XVFB_WHD -nolisten tcp &> ./logs/xvfb.log & 9 | xvfb_pid="$!" 10 | 11 | # possible race condition waiting for Xvfb. 12 | sleep 5 13 | 14 | # Check if git repo exist, else download it from GIT_URL 15 | printf "\n>\n> Repository check \n" 16 | if [ -z "$(ls -A ./git_repos)" ]; then 17 | printf "> \tUsing single repo \n" 18 | 19 | # Check if git repo needs to be cloned 20 | if [ -z "$(ls -A ./git_repo)" ]; then 21 | # Check if GIT_URL is a local folder 22 | if [[ ${INPUT_GIT_URL:0:2} == "./" ]]; then 23 | printf "> \tUsing local repository: $(sed "s/.\//\/github\/workspace\/&/g" <<< ${INPUT_GIT_URL})" 24 | # The action working directory im ounted as /github/workspace 25 | cp -rf $(sed "s/.\//\/github\/workspace\/&/g" <<< ${INPUT_GIT_URL}) ./git_repo 26 | else 27 | # Check if git repo need token 28 | if [ "${INPUT_GIT_TOKEN}" == "" ]; then 29 | printf "> \tCloning from public: ${INPUT_GIT_URL}" 30 | timeout 25s git clone ${INPUT_GIT_URL} ./git_repo >/dev/null 2>&1 31 | else 32 | printf "> \tCloning from private: ${INPUT_GIT_URL}" 33 | # Add git token to access private repository 34 | timeout 25s git clone $(sed "s/git/${GIT_TOKEN}\@&/g" <<< ${INPUT_GIT_URL}) ./git_repo >/dev/null 2>&1 35 | fi 36 | fi 37 | fi 38 | 39 | 40 | if [ -z "$(ls -A ./git_repo)" ]; then 41 | # // TODO: Add multi repo support 42 | printf "\n\nERROR: No Git repository found" 43 | exit 2 44 | fi 45 | 46 | printf "\n> \tUsing volume mounted git repo" 47 | gource --output-custom-log ./development.log ./git_repo >/dev/null 2>&1 48 | else 49 | # // TODO: Add multi repo support 50 | printf "\n\nERROR: Currently multiple repos are not supported" 51 | exit 1 52 | fi 53 | 54 | # Set start and stop date if empty 55 | #printf "\n>\n> Check if start and end date is set\n" 56 | #if [ "${INPUT_GOURCE_START_DATE}" = "" ]; then 57 | # # // TODO: This needs some attention when used with multiple repos 58 | # cd ./git_repo 59 | # printf "\n> \tStart date is empty\n" 60 | # first_commit=git rev-list --max-parents=0 HEAD 61 | # echo "First commit: $first_commit" 62 | # echo $(git show -s --format=%cd --date=short $first_commit) 63 | # export INPUT_GOURCE_START_DATE=$(git show -s --format=%cd --date=short $first_commit) 64 | # printf "\n> \tSet start date to: $INPUT_GOURCE_START_DATE\n" 65 | # cd .. 66 | #else 67 | # printf "\n> \tStart date is set to: $INPUT_GOURCE_START_DATE\n" 68 | #fi 69 | #if [ "${INPUT_GOURCE_STOP_DATE}" = "" ]; then 70 | # # // TODO: This needs some attention when used with multiple repos 71 | # cd ./git_repo 72 | # printf "\n> \tEnd date is empty\n" 73 | # last_commit=git rev-parse HEAD 74 | # echo "last commit: $last_commit" 75 | # echo $(git show -s --format=%cd --date=short $last_commit) 76 | # export INPUT_GOURCE_STOP_DATE=$(git show -s --format=%cd --date=short $last_commit) 77 | # printf "\n> \tSet end date to: $INPUT_GOURCE_STOP_DATE\n" 78 | # cd .. 79 | #else 80 | # printf "\n> \tEnd date is set to: $INPUT_GOURCE_STOP_DATE\n" 81 | #fi 82 | 83 | # Set proper env variables if we have a logo. 84 | printf "\n>\n> Logo check" 85 | if [ "$INPUT_LOGO_URL" != "" ]; then 86 | if [[ $INPUT_LOGO_URL =~ ^https?:\/\/.+(png|jpg)(\?[a-z=0-9-]+)?$ ]]; then 87 | printf "\n> \tDownloading file" 88 | wget -O ./logo.image $INPUT_LOGO_URL >/dev/null 2>&1 89 | else 90 | printf "\n> \tUsing local file" 91 | mv "./git_repo/$INPUT_LOGO_URL" ./logo.image 92 | fi 93 | 94 | convert -geometry x160 ./logo.image ./logo.image 95 | 96 | printf "\n> \tUsing logo from: ${INPUT_LOGO_URL} \n" 97 | export LOGO=" -i ./logo.image " 98 | export LOGO_FILTER_GRAPH=";[with_date][2:v]overlay=main_w-overlay_w-40:main_h-overlay_h-40[with_logo]" 99 | export FILTER_GRAPH_MAP=" -map [with_logo] " 100 | else 101 | printf "\n> \tNo logo provided, skipping logo setup\n" 102 | export FILTER_GRAPH_MAP=" -map [with_date] " 103 | fi 104 | 105 | # Auto fetch contributor avatars 106 | printf "\n>\n> Auto fetch contributor avatars: ${INPUT_AVATARS_AUTO_FETCH}" 107 | if [ "${INPUT_AVATARS_AUTO_FETCH}" == "true" ]; then 108 | printf "\n> \tFetching all contributors\n" 109 | contributorCount=0 110 | avatarsCount=0 111 | 112 | while IFS='|' read -ra author; do 113 | ((contributorCount=contributorCount+1)) 114 | name=${author[0]} 115 | name="${name#"${name%%[![:space:]]*}"}" # This hack removes leating and trailing spaces 116 | name="${name%"${name##*[![:space:]]}"}" 117 | email=${author[1]} 118 | email="${email#"${email%%[![:space:]]*}"}" 119 | email="${email%"${email##*[![:space:]]}"}" 120 | 121 | 122 | # Use github api to get avatar url using the author name or email 123 | avatar_by_name=$(wget -O - -o /dev/null https://api.github.com/users/$name | jq -r '.avatar_url') 124 | 125 | if ([ "$avatar_by_name" != "null" ] && [ ! -z "$avatar_by_name" ]); then 126 | printf "\n> \t\tDownloading avatar for $name from: $avatar_by_name" 127 | wget -O "/gource/avatars/$name.png" $avatar_by_name >/dev/null 2>&1 128 | ((avatarsCount=avatarsCount+1)) 129 | continue 130 | fi 131 | 132 | avatar_by_email=$(wget -O - -o /dev/null https://api.github.com/search/users?q=$email | jq -r '.items[0].avatar_url') 133 | if ([ "$avatar_by_email" != "null" ] && [ ! -z "$avatar_by_name" ]); then 134 | printf "\n> \t\tDownloading avatar for $email from: $avatar_by_email" 135 | wget -O "/gource/avatars/$name.png" $avatar_by_email >/dev/null 2>&1 136 | ((avatarsCount=avatarsCount+1)) 137 | continue 138 | fi 139 | done <<< "$(git --git-dir /gource/git_repo/.git log --pretty="%aN | %aE" | sort | uniq)"; 140 | 141 | printf "\n>\n> \tFound $contributorCount contibutors" 142 | printf "\n> \tSuccessfully fetched $avatarsCount avatars" 143 | else 144 | printf "\n> \tAuto fetch is disabled, fall back to avatars directory\n" 145 | 146 | # Copy user imgages if provided 147 | printf "\n>\n> Avatars check" 148 | if [ "${INPUT_AVATARS_URL}" != "" ]; then 149 | printf "\n> \tCopy avatars directory: ${INPUT_AVATARS_URL}\n" 150 | find "/github/workspace/${INPUT_AVATARS_URL}" -type f -exec cp {} /gource/avatars \; 151 | else 152 | printf "\n> \tNo avatars directory provided, skipping avatars setup\n" 153 | fi 154 | fi 155 | 156 | 157 | # Run the visualization 158 | printf "\n>\n> Starting gource script\n" 159 | /usr/local/bin/gource.sh 160 | printf "\n> Gource script completed" 161 | 162 | # Copy logs and output file to mounted directory 163 | printf "\n>\n> Clean up" 164 | printf "\n> \tCreate output directory /github/workspace/gource" 165 | mkdir -p /github/workspace/gource/logs 166 | printf "\n> \tCopy generated mp4 to /github/workspace/gource" 167 | cp ./output/gource.mp4 /github/workspace/gource 168 | printf "\n> \tCopy logs to /github/workspace/gource/logs" 169 | cp ./logs/* /github/workspace/gource/logs 170 | chmod -R 777 /github/workspace/gource 171 | 172 | printf "\n> \tDelete working directory" 173 | rm -r /gource 174 | 175 | # If gource.mp4 dont exist exit with error 176 | if [ ! -f /github/workspace/gource/gource.mp4 ]; then 177 | printf "\n>\n> ERROR: Can't find: /github/workspace/gource/gource.mp4\n>" 178 | exit 2 179 | fi 180 | 181 | # Exit 182 | printf "\n>\n> Done.\n>" 183 | exit 0 184 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 5 | 6 |

7 | 8 | 9 |

Gource Action

10 |

Action to visualize your source code using gource

11 |

Core image is comming from: utensils/Envisaged

12 |
13 | 14 | 15 |

16 | 17 | 18 | 19 |

20 | 21 |
22 | 23 | 24 |

25 | Getting Started • 26 | Settings • 27 | Advanced example • 28 | Advanced Settings • 29 | Todos • 30 | Maintainer 31 |

32 | 33 |
34 | 35 | ## Getting Started 36 | This is a minimal setup example to visualize the local repository. 37 | 38 | Place the following in `./.github/workflows/gource.yml` 39 | ```yml 40 | name: Gource Action 41 | on: 42 | push: 43 | branches: 44 | - master 45 | 46 | jobs: 47 | action: 48 | runs-on: ubuntu-latest 49 | 50 | steps: 51 | - name: 'Checkout' 52 | uses: actions/checkout@v4 53 | with: 54 | fetch-depth: 0 55 | 56 | - name: 'Gource Action' 57 | uses: nbprojekt/gource-action@v1 58 | 59 | - name: 'Upload gource video' 60 | uses: actions/upload-artifact@v4 61 | with: 62 | name: Gource 63 | path: ./gource/gource.mp4 64 | ``` 65 | > After the workflows have successfully completed, you can download the MP4 file of your artifacts. 66 | > Or use it in another Job. 67 | 68 | 69 | ## Settings 70 | Keys can be added directly to your .yml config file or referenced from your project Secrets storage. 71 | 72 | | Key Name | Required? | Default | Description | 73 | |--------------------------- |----------- |---------------------- |------------------------------------------------------------------------------------------------------------ | 74 | | git_url | false | ./ | Location of git repository. Can also be an remote repository e.g.: https://github.com/acaudwell/Gource.git | 75 | | git_token | false | | If the provided repository is private, the action need an token with read scope. | 76 | | logo_url | false | | Displayed icon on bottom right corner. Can be local "./logo.png" or Url. For Url it must be png or jgp | 77 | | avatars_auto_fetch | false | false | Tries to fetch user avatar from all contributors. If this is enable "avatars_url" will be ignored. | 78 | | avatars_url | false | | Path of local directory containing user avatars. | 79 | 80 | ## Advanced Example 81 | Lets use a more advanced setup to visualize the development from the [Docker CLI][docker-cli]. 82 | ```yml 83 | name: Gource Action for Docker CLI 84 | on: 85 | push: 86 | branches: 87 | - master 88 | 89 | jobs: 90 | action: 91 | runs-on: ubuntu-latest 92 | 93 | steps: 94 | - name: 'Gource Action' 95 | uses: nbprojekt/gource-action@v1 96 | with: 97 | git_url: https://github.com/docker/cli 98 | gource_title: 'Docker CLI' 99 | logo_url: 'https://user-images.githubusercontent.com/24683383/92395924-70189f80-f124-11ea-815c-aa4d9f4de29d.png' 100 | gource_resolution: '1080p' 101 | gource_fps: 60 102 | gource_font_size: 40 103 | gource_start_date: '2016-04-18' 104 | gource_stop_date: '2019-12-31' 105 | 106 | - uses: actions/upload-artifact@v4 107 | with: 108 | name: gource 109 | path: ./gource/gource.mp4 110 | ``` 111 | > This action can take up to _17 Minutes_ 112 | 113 | ## Gource Settings 114 | This settings are all supported setting for [gource][gource-homepage] itself. 115 | A full list of all available options can be found [here][gource-docs]. 116 | 117 | | Key Name | Required? | Default | Description | 118 | |--------------------------- |----------- |---------------------- |------------------------------------------------------------------------------------------------------------ | 119 | | gource_resolution | false | 1080p | Used gource resolution (2160p, 1440p, 1080p, 720p). | 120 | | gource_title | false | Title | Set a title. | 121 | | gource_fps | false | 60 | Used gource fps. | 122 | | gource_auto_skip_seconds | false | 0.5 | Skip to next entry if nothing happens for a number of seconds. | 123 | | gource_background_color | false | 0a0a0a | Background colour in hex. | 124 | | gource_overlay_background_color | false | 202021 | Overlay background colour in hex. | 125 | | gource_font_color | false | F0F0F0 | Font color used by the date and title in hex. | 126 | | gource_overlay_font_color | false | F0F0F0 | Font color used by the overlay in hex. | 127 | | gource_font_size | false | 44 | Font size used by the date and title. | 128 | | gource_camera_mode | false | overview | Camera mode (overview, track). | 129 | | gource_dir_depth | false | 3 | Draw names of directories down to a specific depth in the tree. | 130 | | gource_filename_time | false | 2 | Duration to keep filenames on screen (>= 2.0). | 131 | | gource_hide_items | false | mouse,date,filenames | Hide one or more display elements from the list below. | 132 | | gource_max_user_speed | false | 500 | Max speed users can travel per second. | 133 | | gource_seconds_per_day | false | 0.1 | Speed of simulation in seconds per day. | 134 | | gource_time_scale | false | 1.5 | Change simulation time scale. | 135 | | gource_user_scale | false | 1.2 | Change scale of user avatars. | 136 | | gource_start_date | false | (date of first commit)| Start with the first entry after the supplied date and optional time. | 137 | | gource_stop_date | false | (data of last commit) | Stop after the last entry prior to the supplied date and optional time. | 138 | | gource_file_filter | false | | Filter out file paths matching the specified regular expression. | 139 | 140 | > More comming soon. 141 | > If you are missin a parameter that you need just create a new issue with the title `Add support for --paramer-name` and `Feature Request: New Parameter`label. 142 | 143 | ## Todos 144 | 145 | - #1 Visualizing Multiple Repositories 146 | 147 | ## Maintainer 148 | | [![NbProjekt](https://avatars3.githubusercontent.com/u/24683383?v=3&s=80)](https://github.com/NBprojekt) | 149 | | :---: | 150 | 151 | 152 | [docker-cli]: https://github.com/docker/cli 153 | [gource-homepage]: https://gource.io/ 154 | [gource-docs]: https://github.com/acaudwell/Gource/blob/master/README.md 155 | --------------------------------------------------------------------------------