I use continuous integration with Travis to run my unit tests on every commit. However, sometimes all I want to do is edit the README. Is there a way to skip Travis builds if all the changes are restricted to a whitelisted set of files?
There's no way to directly make Travis dynamically determine, based only on the type of file that has been changed, if it should run a build.
However, Travis will ignore any commit with [ci skip] or [skip ci] in the commit message.
Perhaps you could use a git hook (say prepare-commit-msg or similar) to append [ci-skip] to the commit message when only .md files have been modified.
In the git hook, you could detect this scenario with a command like git diff --exit-code --name-only -- . ':(exclude)*.md'.
In action:
$ git diff --name-only
README.md
$ git diff --exit-code --name-only -- . ':(exclude)*.md'
$ echo $?
0
If any non *.md files have been changed, the command will return 1, otherwise 0.
Related
I am using Xcode Cloud with my iOS project. There are a few workflows based on branches and tags. Commonly one of them is finishing with app publication on the Test Flight.
My goal is to make an automation that will be run on develop branch every time when I will make some push. This automation will arise when script will find #promote tag inside commit message.
My first approach was to use post build script in Xcode Cloud as shown below:
#!/bin/sh
# ci_post_xcodebuild.sh
# BeforeDaily
#
# Created by Piotrek on 28/08/2022.
#
cd "$CI_WORKSPACE"
MESSAGE=$(git log -1 --oneline --format=%s | sed 's/^.*: //')
if [[ "$MESSAGE" == *"#promote"* ]]; then
echo "Merging develop into stage"
git fetch --all
git checkout --track -b stage origin/stage
git merge develop
git push origin stage
git checkout develop
echo "Done"
else
echo "There is nothing to do here..."
fi
This approach was promising but Xcode Cloud does not have write permissions on the Github project and it is not possible to change it. The result of the script is here:
2022-08-28T21:37:40.713643324Z Merging develop into stage
2022-08-28T21:37:42.747978838Z From http://github.com/<username>/<project_name>
2022-08-28T21:37:42.748494378Z * [new branch] develop -> origin/develop
2022-08-28T21:37:42.749001513Z * [new branch] main -> origin/main
2022-08-28T21:37:42.749224260Z * [new branch] stage -> origin/stage
2022-08-28T21:37:42.749514956Z Switched to a new branch 'stage'
2022-08-28T21:37:42.749752757Z branch 'stage' set up to track 'origin/stage'.
2022-08-28T21:37:42.750006530Z fatal: refusing to merge unrelated histories
2022-08-28T21:37:42.852059197Z remote: Write access to repository not granted.
2022-08-28T21:37:42.852480361Z fatal: unable to access 'http://github.com/piotrekjeremicz/beforedaily-swiftui-app.git/': The requested URL returned error: 403
2022-08-28T21:37:42.852854256Z Switched to branch 'develop'
2022-08-28T21:37:42.853020173Z Done
So the question is:
Is there any method that could provide me automatic merge based on commit message content?
I could not find any other solution than make a clean clone and work on fresh git repository. Everything is done in Xcode Cloud Workflow Here is a final ci_post_xcbuild.sh that makes a merge to stage if some message on develop contains #promote string.
#!/bin/sh
cd "$CI_WORKSPACE"
MESSAGE=$(git log -1 --oneline --format=%s | sed 's/^.*: //')
if [[ "$CI_BRANCH" == develop && "$MESSAGE" == *"#promote"* ]]; then
echo "Automerge develop branch into stage"
mkdir tempclone
cd tempclone
git clone https://x-access-token:$GITHUB_TOKEN#github.com/github_account/github_repo_name.git
cd beforedaily-swiftui-app
git config --global user.email "xcodecloud#jeremicz.com"
git config --global user.name "Xcode Cloud"
git checkout --track -b stage origin/stage
git merge origin/develop
git push origin stage
cd ../../
rm -r tempclone
else
echo "There is nothing to do here..."
fi
This script works with Github Token as an environment value that could be setup in Workflow settings.
I'm trying to set up jenkins to run some pipelines for me. As part of my pipeline, I want to checkout a second git repository, which I am placing into a subdirectory of the workspace.
However, this pipeline step will fail on a clean workspace, with an error like:
! [new branch] develop -> origin/develop (unable to update local ref)
error: cannot lock ref 'refs/remotes/origin/master': unable to resolve reference 'refs/remotes/origin/master': Not a directory
From what I can tell, this is happening because git is failing to create the .git/refs/remotes/origin/master file (however it does manage to create the .git/refs/remotes/origin/ directory, which isn't created by the git init command).
Upon playing around, I can reproduce this issue in the docker container by creating a new empty directory and running
git init
git fetch --tags --force --progress -- {giturl} +refs/heads/*:refs/remotes/origin/*
which appears to be what the jenkins step is doing.
If I run the git fetch a second time, it will then succeed.
So far, this is all within a mounted volume in the container. If I try to recreate the problem not in a mounted container, I can't. The
git init
git fetch --tags --force --progress -- {giturl} +refs/heads/*:refs/remotes/origin/*
steps work as expected, meaning that something appears to be going wrong within the mounted volume for some reason.
Does anyone know what might causing these issues within the mounted volume?
Incidentally I also have a stage doing:
bat "\"C:/Program Files/LLVM/bin/clang-format.exe\" -n --style=file --fallback-style=none .\\Source\\*.c .\\Source\\*.cpp .\\Source\\*.h .\\Source\\*.hpp 2>&1 | python ./libraries/clang-to-junit.py ${WORKSPACE} Clang-Format > clang-format-results.xml"
bat "type clang-format-results.xml"
junit allowEmptyResults: true, skipOldReports: true, skipPublishingChecks: true, testResults: 'clang-format-results.xml'
which creates a clang-format-results.xml file to report results of clang format. However the junit step fails to find the file if it's newly created, despite the type command outputting the file just fine. Seems like this could be related also to filesystem issues...
I am new to bitbuckt pipeline. To my node project I have added bitbucket-pipelines.yml in the pipeline I have a step to build and push container to ECR and another step to deploy.
Now each time I make a change to bitbucket-pipelines.yml it build and pushes a new image to ECR and deploys.
I do not what the piepline to trigger when I make changes to bitbucket-pipelines.yml. I only want the pipeline to trigger when I make changes to my application. Am I setting up the project wrong?
my project structure.
.
├── bitbucket-pipelines.yml
├── Dockerfile
├── index.js
├── node_modules
├── package.json
├── package-lock.json
└── README.md
There are a few possible options:
1. Add [skip ci] to your git commit message
Whenever you change the bitbucket-pipelines.yml on its own, add "[skip ci]" (without quotes) somewhere in your Git commit message. This will prevent the pipeline from running when you push to the Bitbucket remote.
Advantages:
It's easy and simple.
Disadvantages:
You have to remember to manually write the "[skip ci]" text. It's easy to forget, or perhaps a new team member will not know about it.
2. Use a Git Hook to automatically modify your git commit message
Write a Git Hook script that will automatically insert the "[skip ci]" text into the Git commit message. The script will have to do something like this:
After a local commit, check the latest commit to see which files were changed. Use something like git diff --name-only HEAD~0 HEAD~1
If bitbucket-pipelines.yml was the only file changed, modify the commit to insert "[skip ci]" into the commit message.
More info about Git Hooks:
https://githooks.com/
https://www.atlassian.com/git/tutorials/git-hooks
https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks
Advantages:
It's fully automatic. No need to manually tag your commit messages.
Disadvantages:
Creating the script may not be easy.
Each cloned repo needs to configure the git hooks. See: Can Git hook scripts be managed along with the repository?
3. Make the bitbucket-pipelines.yml check for the file changes
Add a section in the yml build script to check which file was changed in the latest commit.
The script in the yml will have to do something like this:
Check the latest commit to see which files were changed. Use something like git diff --name-only HEAD~0 HEAD~1
If bitbucket-pipelines.yml was the only file changed, abort the CI build immediately, with an exit 0 statement.
Advantages:
It's fully automatic. No need to manually tag your commit messages.
No need to write Git Hook scripts.
Disadvantages:
The Docker image of your CI build will take 1-5 minutes to load, and then abort itself. This is a bit ineffecient and it will consume some of your build minutes.
Because the CI build will still run for a few minutes, it will pollute your CI build history with build runs that didn't do anything.
4. Use a Conditional Step with "changesets" and "includePaths"
Define a changesets with an includePaths to execute a step only if one of the modified files matches the expression in includePaths.
pipelines:
default:
- step:
name: build-frontend-artifact
condition:
changesets:
includePaths:
# only xml files directly under resources directory
- "src/main/resources/*.xml"
# any changes in frontend directory
- "src/site/**"
script:
- echo "Building frontend artifact"
Source and more info here: https://bitbucket.org/blog/conditional-steps-and-improvements-to-logs-in-bitbucket-pipelines
I've created a Jenkins Multibranch Pipeline with the GitHub Branch Source plugin. The Jenkinsfile essentially just calls a Cake Build script (build.ps1, build.cake) that contains all the build/deploy logic. This allows me to move to another CI service easily.
Unfortunately, I cannot seem to figure out how to add my Cake Build scripts as a trusted file so that PR's from forks will pull the files from the source repo instead. The Trust setting of the Discover pull requests from forks behavior seems to indicate that there can be other trusted files besides Jenkinsfile:
Nobody
Pull requests from forks will all be treated as untrusted. This means that where Jenkins requires a trusted file (e.g. Jenkinsfile) the contents of that file will be retrieved from the target branch on the origin repository and not from the pull request branch on the fork repository.
However, I cannot seem to find any documentation on adding other trusted files. The primary reason for this is to prevent a PR from a fork from accessing credentials from the Cake script. They wouldn't be able to change Jenkinsfile, but they could still change the Cake script to expose the credentials.
Is it actually possible to add other trusted files?
It seems like Jenkins does not support this. My solution is checking out the untrusted files manually from the base version instead. First getting the commit 's hash of the base version with:
def commit = sh(
script: 'git rev-parse HEAD',
returnStdout: true
).trim()
def base = sh(
script: "git rev-list --parents -n 1 ${commit}",
returnStdout: true
).trim().split('\\s+')[2]
git rev-list --parents -n 1 ${commit} will return the hash of current commit, which is a merge commit that was created by Jenkins; the latest commit of the PR and the latest commit of the target branch, separated by a space (e.g. 05e9322574ea03003f87dcbb44f172e6fa62581f b3f6ef892af9c645f490106757d7d05df3a26060 069ffd55ae36414a51b4de166aef86966f9447a8). Hence, we grab the hash of the latest commit of the target branch by trim().split('\\s+')[2].
Now we can do sh "git checkout ${base} FILE" on any file that we don't trust from the PR.
This does not works if the PR is already merged with the latest version of target branch. So what I did is something like this:
// revert untrusted files to the base version and backup it before we execute any untrusted code so the attacker
// don't have a chance to put a malicious content
def latest = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
sh "git checkout origin/${env.CHANGE_TARGET}"
def baseCompose = readFile('docker-compose.yml')
// switch back to latest commit
sh "git checkout ${latest}"
sh 'git clean -d -f -f -q -x'
I wish to write the git change log for two particular builds in a file in Jenkins.
I have used " git change log " plugin it shows the difference between latest one and the previous one and follows;
Not for the particular two builds.
Eg:
input : build1, build10
Output should be the git change log between build1 and build10
You need to get the GIT_COMMIT Environment variable from the two build you wanted and then do a git log between those commits.
Example: git log --pretty=oneline COMMIT_X COMMIT_Y
If you want the difference in the repo files itself you have to do git diff between those commits.
Example:git diff COMMIT_X COMMIT_Y